HDU 5768Lucky7(多校第四场)容斥+中国剩余定理(扩展欧几里德求逆元的)+快速乘法
地址:http://acm.hdu.edu.cn/showproblem.php?pid=5768
Lucky7
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
When ?? was born, seven crows flew in and stopped beside him. In its childhood, ?? had been unfortunately fall into the sea. While it was dying, seven dolphins arched its body and sent it back to the shore. It is said that ?? used to surrounded by 7 candles when he faced a extremely difficult problem, and always solve it in seven minutes.
?? once wrote an autobiography, which mentioned something about himself. In his book, it said seven is his favorite number and he thinks that a number can be divisible by seven can bring him good luck. On the other hand, ?? abhors some other prime numbers and thinks a number x divided by pi which is one of these prime numbers with a given remainder ai will bring him bad luck. In this case, many of his lucky numbers are sullied because they can be divisible by 7 and also has a remainder of ai when it is divided by the prime number pi.
Now give you a pair of x and y, and N pairs of ai and pi, please find out how many numbers between x and y can bring ?? good luck.
?? once wrote an autobiography, which mentioned something about himself. In his book, it said seven is his favorite number and he thinks that a number can be divisible by seven can bring him good luck. On the other hand, ?? abhors some other prime numbers and thinks a number x divided by pi which is one of these prime numbers with a given remainder ai will bring him bad luck. In this case, many of his lucky numbers are sullied because they can be divisible by 7 and also has a remainder of ai when it is divided by the prime number pi.
Now give you a pair of x and y, and N pairs of ai and pi, please find out how many numbers between x and y can bring ?? good luck.
Input
On the first line there is an integer T(T≤20) representing the number of test cases.
Each test case starts with three integers three intergers n, x, y(0<=n<=15,0<x<y<1018) on a line where n is the number of pirmes.
Following on n lines each contains two integers pi, ai where pi is the pirme and ?? abhors the numbers have a remainder of ai when they are divided by pi.
It is guranteed that all the pi are distinct and pi!=7.
It is also guaranteed that p1*p2*…*pn<=1018 and 0<ai<pi<=105for every i∈(1…n).
Each test case starts with three integers three intergers n, x, y(0<=n<=15,0<x<y<1018) on a line where n is the number of pirmes.
Following on n lines each contains two integers pi, ai where pi is the pirme and ?? abhors the numbers have a remainder of ai when they are divided by pi.
It is guranteed that all the pi are distinct and pi!=7.
It is also guaranteed that p1*p2*…*pn<=1018 and 0<ai<pi<=105for every i∈(1…n).
Output
For each test case, first output "Case #x: ",x=1,2,3...., then output the correct answer on a line.
Sample Input
2
2 1 100
3 2
5 3
0 1 100
Sample Output
Case #1: 7
Case #2: 14
Hint
For Case 1: 7,21,42,49,70,84,91 are the seven numbers.
For Case2: 7,14,21,28,35,42,49,56,63,70,77,84,91,98 are the fourteen numbers.
题意:
就是问有多少个幸运数,然后幸运数呢,就是能被7整除的数,但是这些数可能被污染,哪些数会被污染呢,就是有n种方法会被污染,每种方法给出一个ai,一个
pi,如果幸运数%pi等于ai就会被污染,然后给你一个区间,问这个区间有多少个没被污染的幸运数。
题解:
这题一开始就知道是个中国剩余定理,然后看了多篇题解,发现要用容斥+中国剩余定理,然后发现要爆long long,必须要加上一个快速乘法=。=,然后求逆元的时候
不能用费马小定理=。=,因为快速幂要爆long long,用快速乘法就会T(I good vegetable a),最后只有学了一波欧几里德求逆元TAT。
先对着标程看了半天他在写啥,然后发现标程是先状态压缩,然后再容斥=。=,看标程就看了好久,我是不是没救了QAQ。
代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 #include<stack> 7 #include<cstring> 8 #include<queue> 9 #include<set> 10 #include<string> 11 #include<map> 12 #define inf 9223372036854775807 13 #define INF 9e7+5 14 #define PI acos(-1) 15 using namespace std; 16 typedef long long ll; 17 typedef double db; 18 typedef long long LL; 19 const int maxn = 1e2 + 5; 20 const int mod = 1e9 + 7; 21 const db eps = 1e-9; 22 ll n, l, r, ai[maxn], pi[maxn]; 23 24 int Bitcount(ll x) { 25 return x ? Bitcount(x >> 1) + (x&1LL) : 0; 26 } //求当前状态选择的方程的个数 27 28 ll q_mul(ll a, ll b, ll mod) { 29 ll ret = 0; 30 while (b) { 31 if (b & 1) ret = (ret + a) % mod; 32 b >>= 1; 33 a = (a + a) % mod; 34 } 35 return ret; 36 } // 快速乘法 37 38 void Ex_Gcd(ll a, ll b, ll &x, ll &y){ 39 ll d; 40 if(b==0){ 41 x=1,y=0; 42 return; 43 } 44 Ex_Gcd(b,a%b,y,x); 45 y-=a/b*x; 46 } // 这里直接抄的标程的函数。。 47 48 ll CRT(ll p[], ll a[], ll cnt) { 49 ll M = 1; 50 ll res = 0; 51 for (int i = 0; i <= cnt; i++) M *= p[i]; 52 for (int i = 0; i <= cnt; i++) { 53 ll m = M / p[i], x, y; 54 Ex_Gcd(m, p[i], x, y); 55 res = (res + q_mul(q_mul(x, m, M), a[i], M)) % M; 56 } 57 return (res + M) % M; 58 } 59 60 ll solve(ll x) { 61 ll p[maxn], m[maxn], ans = 0; 62 p[0] = 7, m[0] = 0; 63 if (!x) return 0; 64 for (ll i = 1; i < (1LL << n); i++) { 65 ll num = Bitcount(i), t = 7, cnt = 0; 66 for (ll j = 0; j < n; j++) { 67 if (i & (1LL << j)) { 68 p[++cnt] = pi[j]; 69 m[cnt] = ai[j]; 70 t *= pi[j]; 71 } 72 } 73 ll res = CRT(p, m, cnt); 74 if (res > x) continue; 75 if (num & 1) ans -= (x - res) / t + 1; //容斥一下 76 else ans += (x - res) / t + 1; 77 } 78 return ans + x / 7; 79 } 80 81 int main() { 82 //cin.sync_with_stdio(false); 83 //freopen("tt.txt", "r", stdin); 84 //freopen("isharp.out", "w", stdout); 85 int t, cas = 1; 86 87 cin >> t; 88 while (t--) { 89 cin >> n >> l >> r; 90 for (int i = 0; i < n; i++) 91 cin >> pi[i] >> ai[i]; 92 printf("Case #%d: %I64d\n", cas++, solve(r) - solve(l-1)); 93 } 94 return 0; 95 }