HDU 5768 Lucky7 (中国剩余定理+容斥)

题目链接: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 }

 

posted @ 2016-08-01 16:28  Recoder  阅读(186)  评论(0编辑  收藏  举报