题意:
给出x, y, m[1...n], a[1..n].
在[x,y]中寻找 p % 7 = 0 且对任意(1<= i <=n) p % m[i] != a[i] 的数字的个数
分析:
可用容斥定理,先在[x,y]找出所有7的倍数,再根据多个模线性方程连立,去掉所有不合法的
因 m[1...n] 互质,故可直接使用中国剩余定理.
并且需要在其中用 快速加法 防止超 long long
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 using namespace std; 5 #define LL long long 6 const int MAXN = 20; 7 LL ExtGcd(LL a,LL b,LL &x,LL &y) 8 { 9 if (b == 0) {x = 1; y = 0; return a;} 10 LL d = ExtGcd(b, a%b, y, x); 11 y -= a / b * x; 12 return d; 13 } 14 LL Mul(LL a,LL b,LL MOD) 15 { 16 a%=MOD; b%=MOD; 17 LL res = 0; 18 while(b) 19 { 20 if (b&1) res = (res + a) % MOD; 21 a <<= 1; if(a > MOD) a-=MOD; 22 b >>= 1; 23 } 24 return res; 25 } 26 void CRT(LL &ans,LL &M, LL a[],LL m[],int k) //X = a[i] ( mod m[i] )(m[i]两两互质) 27 { //解为 X = ans + M * t (0 <= ans <= M) 28 M = 1, ans = 0; 29 LL x, y, Mi; 30 for (int i = 0; i < k; i++) M *= m[i]; 31 for (int i = 0; i < k; i++) 32 { 33 Mi = M / m[i]; 34 ExtGcd(m[i], Mi, x, y); 35 ans = (ans + Mul( Mul(y, Mi, M), a[i], M)) % M; 36 } 37 if(ans < 0) ans += M; 38 } 39 int t, n; 40 LL x, y; 41 LL m1[MAXN], a1[MAXN], m[MAXN], a[MAXN]; 42 LL Cal(LL m,LL a) 43 { 44 LL x0 = x + m - a; 45 LL y0 = y + m - a; 46 return y0 / m - (x0 - 1) / m;//计算[x,y]中有多少p % m = a 47 } 48 int main() 49 { 50 scanf("%d", &t); 51 for(int tt = 1; tt <= t; tt++) 52 { 53 scanf("%d%lld%lld", &n, &x, &y); 54 for(int i = 0; i < n ; i++) 55 scanf("%lld%lld", &m1[i], &a1[i]); 56 int cnt = 0; 57 LL ans = Cal(7,0);//找出所有7的倍数 58 for (int i = 1; i < (1<<n); i++)//枚举 59 { 60 cnt = 0; 61 for (int j = 0; j < n; j++) 62 { 63 if (i & (1<<j)) 64 { 65 m[cnt] = m1[j]; 66 a[cnt] = a1[j]; 67 ++cnt; 68 } 69 } 70 m[cnt] = 7; 71 a[cnt] = 0; 72 ++cnt; 73 LL M,A; 74 CRT(A, M, a, m, cnt); 75 if (cnt%2) ans += Cal(M, A);//加奇数个,减偶数个 76 else ans -= Cal(M, A); 77 } 78 printf("Case #%d: %lld ",tt,ans); 79 } 80 }