题意:找出[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;
}