题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768
给你n个同余方程组,然后给你l,r,问你l,r中有多少数%7=0且%ai != bi.
比较明显的中国剩余定理+容斥,容斥的时候每次要加上个(%7=0)这一组。
中间会爆longlong,所以在其中加上个快速乘法(类似矩阵快速幂)。因为普通的a*b是直接a个b相加,很可能会爆。但是你可以将b拆分为二进制来加a,这样又快又可以防爆。
1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <ctime> 10 #include <list> 11 #include <set> 12 #include <map> 13 using namespace std; 14 typedef long long LL; 15 typedef pair <int, int> P; 16 const int N = 1e5 + 5; 17 LL a[17] , b[17], fuck = 1e18; 18 19 LL Fmul(LL a , LL n , LL mod) { //快速乘法 20 LL res = 0; 21 while(n) { 22 if(n & 1) { 23 res = (res + a) % mod; 24 } 25 a = a * 2 % mod; 26 n >>= 1; 27 } 28 return res; 29 } 30 31 LL exgcd(LL a , LL b , LL &x , LL &y) { 32 LL res = a; 33 if(!b) { 34 x = 1; 35 y = 0; 36 } 37 else { 38 res = exgcd(b , a % b , x , y); 39 LL temp = x; 40 x = y; 41 y = temp - a / b * y; 42 } 43 return res; 44 } 45 46 LL CRT(LL a[] , LL m[] , LL n) { 47 LL M = 1 , res = 0; 48 for(LL i = 1 ; i <= n ; i++) { 49 M = M * m[i]; 50 } 51 for(LL i = 1 ; i <= n ; i++) { 52 LL x , y , Mi = M / m[i]; 53 exgcd(Mi , m[i] , x , y); 54 x = (x % m[i] + m[i]) % m[i]; 55 res = (res + Fmul(x * a[i] % M , Mi , M) + M) % M; 56 } 57 if(res < 0) 58 res += M; 59 return res; 60 } 61 62 LL Get(LL n, LL x, LL y) { 63 if(x > n) 64 return 0; 65 else { 66 n -= x; 67 return (LL)(1 + n / y); 68 } 69 } 70 71 int main() 72 { 73 int t, n; 74 LL l , r , md[17], di[17]; 75 scanf("%d", &t); 76 for(int ca = 1; ca <= t; ++ca) { 77 scanf("%d %lld %lld", &n, &l, &r); 78 di[1] = 7, md[1] = 0; 79 for(int i = 1; i <= n; ++i) { 80 scanf("%lld %lld", a + i, b + i); 81 } 82 LL res1 = 0, res2 = 0; 83 int limit = (1 << n) - 1; 84 for(int i = 1; i <= limit; ++i) { 85 int temp = i, index = 1; 86 LL mul = 7; 87 for(int j = 1 ; temp ; ++j) { 88 if(temp & 1) { 89 di[++index] = a[j]; 90 md[index] = b[j]; 91 mul *= a[j]; 92 } 93 temp >>= 1; 94 } 95 if(index % 2) { 96 res1 -= Get(l - 1, CRT(md, di, index), mul); 97 res2 -= Get(r, CRT(md, di, index), mul); 98 } 99 else { 100 res1 += Get(l - 1, CRT(md, di, index), mul); 101 res2 += Get(r, CRT(md, di, index), mul); 102 } 103 } 104 printf("Case #%d: %lld\n",ca, r/7 - (l-1)/7 - (res2 - res1)); 105 } 106 return 0; 107 }
时间: 2024-10-08 21:56:17