hdu 5768 容斥+模线性方程组

来源:互联网 发布:英文论文写作软件 编辑:程序博客网 时间:2024/06/06 17:15

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 = abool 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<<"我是会减少的!!!\n";    }    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\n";        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;    }}


0 0
原创粉丝点击