zoukankan      html  css  js  c++  java
  • hdu 5768 容斥+模线性方程组

    http://acm.hdu.edu.cn/showproblem.php?pid=5768

    题意:给你一个范围,让你找到满足条件的数有多少个。。条件:是7的倍数,%Xi=ai。。

    思路:这个问题明显是个并集这样的问题。。纸上大概写一写就能发现是个容斥的问题。。所以我们先预处理出来每种情况模线性方程的解。。。之后用dfs+状压进行容斥原理(就是把表达式展开+-+-。。。)。。到这里这个题就做完了。。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int n;
    int vis[1<<16];
    long long dp[1<<16][2];
    long long M[16],A[16];
    long long extend_gcd(long long a,long long b,long long &x,long long  &y){
        if(a == 0 && b == 0)return -1;
        if(b ==0 ){
            x = 1;
            y = 0;
            return a;
        }
        long long d = extend_gcd(b,a%b,y,x);
        y -= a/b*x;
        return d;
    }
    long long m[16],a[16];//模数为m,余数为a, X % m = a
    bool solve(long long &m0,long long &a0,long long m,long long a){
        long long y,x;        /*  * 无解返回false,有解返回true;  * 解的形式最后为 a0 + m0 * t  (0<=a0<m0)  */
        long long g = extend_gcd(m0,m,x,y);
        if( abs(a - a0)%g )return false;
        x *= (a - a0)/g;
        x %= m/g;
        a0 = (x*m0 + a0);
        m0 *= m/g;
        a0 %= m0;
        if( a0 < 0 )a0 += m0;
        return true;
    }
    bool MLES(long long &m0 ,long long &a0,int n)//解为  X = a0 + m0 * k
    {
        bool flag = true;
        m0 = 1;
        a0 = 0;
        for(int i = 0; i < n; i++)
            if( !solve(m0,a0,m[i],a[i]) ){
                flag = false;
                break;
            }
        return flag;
    }
    
    void init(int bts){
        int cnt=0;
        for(int i=0;i<n;i++){
            if(bts&(1<<i)){
                m[cnt]=M[i];
                a[cnt++]=A[i];
            }
        }
        m[cnt]=7;
        a[cnt++]=0;
        MLES(dp[bts][0],dp[bts][1],cnt);
    }
    
    long long sl(int bts,long long T){
        long long ret=0;
        ret+=T/dp[bts][0];
        if(dp[bts][1]<=T%dp[bts][0]) ret++;
        return ret;
    }
    long long TM;
    void dfs(int bts,long long T,int c){
        long long ret=0;
        vis[bts]=1;
        if(bts!=0) ret=sl(bts,T);
        if(c) TM+=ret;
        else{
           TM-=ret;
         //  cout<<ret<<"我是会减少的!!!
    ";
        }
        for(int i=0;i<n;i++){
            int nxt=bts|(1<<i);
            if(!vis[nxt]){
                dfs(nxt,T,c^1);
            }
        }
    }
    
    int main(){
        int t,cas=1;
        scanf("%d",&t);
        while(t--){
            long long x,y;
            scanf("%d%lld%lld",&n,&x,&y);
            x--;
            for(int i=0;i<n;i++) scanf("%lld%lld",&M[i],&A[i]);
            for(int i=1;i<(1<<n);i++) init(i);
           // cout<<"FFFF
    ";
            memset(vis,0,sizeof(vis));
            TM=0;
            dfs(0,x,0);
            long long X=x/7-TM;
            memset(vis,0,sizeof(vis));
            TM=0;
            dfs(0,y,0);
            long long Y=y/7-TM;
            printf("Case #%d: ",cas++);
            cout<<Y-X<<endl;
        }
    }



  • 相关阅读:
    点击图片等比缩放
    C# 使用 NPOI 库读写 Excel 文件
    vue url生产二维码
    centos Linux 同步Windows 时间
    centos 搭建 docker sentry
    centos 安装 pip
    webpack 提升90%的构建速度 HardSourceWebpackPlugin
    webpack 原生分析
    webpack 分析
    nodejs——js 实现webSocket 兼容移动端
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672548.html
Copyright © 2011-2022 走看看