题意:求区间中7的倍数并且模pi不等于ai的个数.
相当于求模7等于0的数中扣掉模pi等于ai的个数,这个东西看着就很容斥。先枚举限制条件的组合,然后加上模7等于0这个条件,这一堆条件看着就很中国剩余定理,然后搞出一个前缀区间有多少个符合条件的数,加加减减就行了。(嘴炮5分钟,代码两小时=。=)
trick:中国剩余定理里面会爆longlong,所以换成快速乘法取模。
#include #include #include #include #include usingnamespacestd;
#define maxn 33longlong a[maxn], b[maxn];
int n;
longlong aa[maxn], bb[maxn];
void gcd (longlong a, longlong b, longlong &d, longlong &x, longlong &y) {
if (!b) {
d = a;
x = 1;
y = 0;
}
else {
gcd (b, a%b, d, y, x);
y -= x*(a/b);
}
}
longlong mul (longlong a, longlong b, longlong mod) {
if (b == 0)
return0;
longlong ans = mul (a, b>>1, mod);
ans = ans*2%mod;
if (b&1) ans += a, ans %= mod;
return ans;
}
longlong china (int n, longlong *a, longlong *m, longlong R) {
longlong M = 1, d, y, x = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i< n; i++) {
longlong w = M/m[i];
gcd (m[i], w, d, d, y);
x = (x+ mul (mul (y, w, M), a[i], M)) % M;
}
longlong Min = (x+M)%M;
if (Min && R%M >= Min) {
return (R/M)+1;
}
return R/M;
}
longlong go (int num, int &num_of_1, longlong R) {
num_of_1 = 0;
int cnt = 0;
for (int bit = 0; bit < n; bit++) if (num&(1<7, bb[cnt++] = 0;
return china (cnt, bb, aa, R);
}
longlong solve (longlong x) {
longlong ans = 0;
int num_of_1;
for (int i = 1; i < (1<long long tmp = go (i, num_of_1, x);
if (num_of_1&1)
ans += tmp;
else
ans -= tmp;
}
return ans;
}
int main () {
int t, kase = 0;
scanf ("%d", &t);
while (t--) {
longlong x, y;
scanf ("%d%lld%lld", &n, &x, &y);
for (int i = 0; i < n; i++) {
scanf ("%lld%lld", &a[i], &b[i]);
}
printf ("Case #%d: %lld
", ++kase, (y/7 - (x-1)/7) - (solve (y)-solve (x-1)));
}
return0;
}