题意:
给出一个范围[l,r]以及两个数组a,p,要求在这范围内mod 7 = 0,且mod p[i] != a[i]的数一共有多少个。
思路:
容斥原理,只考虑把a[0] = 0,p[0] = 7,只考虑这mod 7 = 0的数,进行容斥。利用中国剩余定理解同余式组。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
void extend_Euclid(LL a, LL b, LL &x, LL &y) {
if (b == 0) {
x = 1; y = 0;
return;
}
extend_Euclid(b, a % b, x, y);
LL tmp = x;
x = y;
y = tmp - (a / b) * y;
}
LL mul(LL a, LL k, LL m) {
LL res = 0;
while (k) {
if (k & 1LL) res = (res + a) % m;
a = (a + a) % m;
k >>= 1;
}
return res;
}
LL China(LL a[], LL m[], int n, LL R) {
LL M = 1, res = 0;
for (int i = 1; i <= n; i++)
M *= m[i];
for (int i = 1; i <= n; i++) {
LL x, y, Mi = M / m[i];
extend_Euclid(Mi, m[i], x, y);
x = (x % m[i] + m[i]) % m[i];
res = (res + mul(Mi * a[i], x, M)) % M;
}
res = (res + M) % M;
if (res && R % M >= res) return R / M + 1;
return R / M;
}
LL p[20], a[20];
LL solve(LL x, int n) {
LL div[20], mod[20], res = 0;
for (int i = 1; i < (1 << n); i++) {
if (!(i & (1 << 0))) continue;
int cnt = 0;
LL M = 1;
for (int j = 0; j < n; j++) {
if (i & (1 << j)) {
div[++cnt] = p[j];
mod[cnt] = a[j];
M *= p[j];
}
}
LL tmp = China(mod, div, cnt, x);
if (cnt & 1) res += tmp;
else res -= tmp;
}
return res;
}
int main() {
//freopen("in.txt", "r", stdin);
int T, cs = 0;
scanf("%d", &T);
while (T--) {
int n;
LL l, r;
scanf("%d%I64d%I64d", &n, &l, &r);
p[0] = 7; a[0] = 0;
for (int i = 1; i <= n; i++)
scanf("%I64d%I64d", &p[i], &a[i]);
++n;
LL ans = solve(r, n) - solve(l - 1, n);
printf("Case #%d: %I64d\n", ++cs, ans);
}
return 0;
}