HDU-5768-Lucky7-中国剩余定律+容斥

来源:互联网 发布:it维保服务 编辑:程序博客网 时间:2024/05/29 18:17

题意:找出[x,y]中,能被7整除,且除p[i]不等于a[i]的数的个数

思路:用状态压缩,容斥枚举参于中国剩余定律的p然后用中国剩余定律求出MIN,然后当前的个数为如果X mod M>=MIN ,ans=X/M+1

否则ans=X/M  (M是参与中国剩余定律的所有PI值)其中要注意,中国剩余定律中,可能会爆long long 所以要写一个快速乘法。

#include<bits/stdc++.h>using namespace std;int n;long long a[20],b[20];long long aa[20],bb[20];void gcd(long long a,long long b,long long &d,long long &x,long long &y) {    if(!b) {        d=a;x=1;y=0;    }    else {        gcd(b,a%b,d,y,x);        y-=x*(a/b);    }}long long mul(long long a,long long b,long long mod) {///b个a相乘    long long ans=0;    while(b) {        if(b&1LL)            ans=(ans+a)%mod;        b >>=1;        a=(a<<1)%mod;    }    return ans;}long long china(int num,long long * a,long long * m,long long nx,long long  ny) {    long long M=1,d,y,x=0;    for(int i=0;i<num;i++) M*=m[i];    for(int i=0;i<num;i++) {        long long w=M/m[i];        gcd(m[i],w,d,d,y);        x=(x+mul(mul(y,w,M),a[i],M))%M;    }    long long MIN=(x+M)%M;    long long xx,yy;    if(MIN&&ny%M>=MIN) {        yy=ny/M+1;    }    else {        yy=ny/M;    }    if(MIN&&nx%M>=MIN) {        xx=nx/M+1;    }    else {        xx=nx/M;    }      //  cout << "M"<< M <<" "<<"MIN" << MIN << "ans"<<yy-xx <<endl;    return yy-xx;}int main(){    int t;    long long x,y;    int num_of_1;    int kase=0;    scanf("%d",&t);    while(t--) {        scanf("%d%lld%lld",&n,&x,&y);        long long tot=0;        for(int i=0;i<n;i++) {            scanf("%lld%lld",&a[i],&b[i]);        }        a[n]=7;b[n]=0;        for(int i=0;i< (1 << n);i++) {            num_of_1=0;            for(int j=0;j<n;j++) {                if(i&(1<<j)){                    aa[num_of_1]=a[j];                    bb[num_of_1]=b[j];                    num_of_1++;                }            }            aa[num_of_1]=7;            bb[num_of_1]=0;            long long tmp=china(num_of_1+1,bb,aa,x-1,y);            if(num_of_1&1) tot-=tmp;            else tot+=tmp;        }   //     cout << "tot" << tot << endl;        printf("Case #%d: %lld\n",++kase,tot);    }    return 0;}


0 0