题意:
给定0<L<R<1018,给定N≤15个非法条件
即x%pi=ai,ai<pi≤105,∏pi≤1018
求[L, R]区间内能被7整除,且合法的数字的个数
分析: 容斥 加 CRT
非法条件有15个,显然的容斥一下,对于每个条件我们可以用CRT算出个数 但是这里有被7整除的条件,不如把这个条件当作强制条件 之后把全集变成模7域下的全集,即[L, R]整除7的数的个数tot 最后ans=tot−容斥的结果 时间复杂度O(n×2n×nlogC)
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = a; i < b; i++)
const int N = 1e5 + 10;
typedef long long LL;
LL exgcd(LL a, LL b, LL& x, LL& y) {
LL g = a;
if(!b) x = 1, y = 0;
else {
g = exgcd(b, a % b, y, x);
y -= a / b * x;
}
return g;
}
int n;
LL x, y;
int r[N], p[N];
LL a[N], b[N], m[N];
pair<LL, LL> excrt(int n, LL* a, LL* b, LL* m) { //(a * x) % m 同于 b
LL B = 0, M = 1;
for(int i = 1; i <= n; ++i) {
LL A = (M * a[i]) % m[i], c = (b[i] - B * a[i]) % m[i];
LL x, y, g = exgcd(A, m[i], x, y);
if(c % g) return { -1, -1};
x = c / g * x % (m[i] / g);
B += x * M;
M *= m[i] / g;
B %= M;
}
B = (B + M) % M;
if(!B) B = M;
return {B, M};
}
LL cal(LL x, LL B, LL M){
LL ret = x >= B;
ret += (x - B) / M;
return ret;
}
int main()
{
int T, ks = 0;
scanf("%d", &T);
while(T--)
{
scanf("%d%I64d%I64d", &n, &x, &y);
rep(i, 0, n) scanf("%I64d%I64d", &p[i], &r[i]);
LL ans1 = 0, ans2 = 0;
rep(s, 1, 1<<n){
int id = 0;
rep(i, 0, n){
if(s >> i & 1){
++id;
a[id] = 1;
m[id] = p[i];
b[id] = r[i];
}
}
++id;
a[id] = 1; m[id] = 7; b[id] = 0;
auto ret = excrt(id, a, b, m);
LL B, M;
tie(B, M) = ret;
LL tmp = cal(y, B, M) - cal(x - 1, B, M);
if((id - 1) & 1) ans2 += tmp;
else ans2 -= tmp;
}
ans1 = (y / 7) - (x - 1) / 7 - ans2;
printf("Case #%d: %I64d\n", ++ks, ans1);
}
return 0;
}