给你一个区间,问你在这个区间内 不满足模m[i]等于a[i]的 并且能被7整除的个数有几个
我们先求一下在这个区间里的 7 的倍数有多少个,
然后在求 是 7 的倍数,然后又满足 模 m[i] 等于 a[i] 的有多少个,
由于 m[i],a[i] 有 n 个,但是 n 又不超过 15 个,所以我么可以用充斥原理来求,
奇数就 - 偶数 就 + 。
把 m[i],a[i] 的情况用二进制枚举一下,用中国剩余定理求他们的最小的公共数是多少。然后
再求 区间里一共有多少个。
主要熟悉一下中国剩余定理求解线性同余方程。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(x,v) memset(x,v,sizeof(x))
using namespace std;
typedef long long LL;
LL m[20],a[20];
LL s[20];
LL n,x,y;
void exgcd(LL a, LL b, LL &x,LL &y){
if (b == 0){
x = 1; y = 0; return ;
}
exgcd(b,a%b,x,y);
LL tmp = x;
x = y; y = tmp - a / b * y;
return ;
}
LL mul(LL a, LL k, LL M){
LL res = 0;
while(k){
if (k & 1) res = (res + a)%M;
k >>= 1;
a = (a << 1)%M;
}
return res;
}
LL China(){
LL ans = 0,res,M = 1;
for (int i = 0; i <= n; i++){
if (s[i]) M *= m[i];
}
for (int i = 0; i <= n; i++){
if (s[i]){
LL x,y;
LL Mi = M / m[i];
exgcd(Mi,m[i],x,y);
x = (x % m[i] + m[i])% m[i];
ans = ((ans + mul(a[i]*Mi,x,M)%M)+M)%M;
}
}
res = (y + M - ans)/M - (x - 1 + M - ans)/M;//所有符合条件的解为ans = x+k*M,
//可以知道在[1,y]这个区间内,有(M+y-x)/ M个k符合条件,
return res;
}
void init(){
cin>>n>>x>>y;
for (int i = 0; i < n; i++)
scanf("%I64d%I64d",&m[i],&a[i]);
m[n] = 7; a[n] = 0; s[n] = 1;
return;
}
int main(){
int T,num = 1;
cin>>T;
while(T--){
init();
LL ans = 0;
for (int i = 0; i < (1 << n); i++){ //二进制压缩。
int k = 0;
for (int j = 0; j < n; j++){
if (i & (1 << j)) s[j] = 1,k++; else s[j] = 0;
}
k = k & 1 ? -1 : 1; //这里用到了容斥原理。奇数 -,偶数 +。
ans += China()*k; //i 一定从 0 开始,0 是算 7 的倍数的。
}
printf("Case #%d: ",num++);
printf("%I64d\n",ans);
}
return 0;
}