题目:http://acm.hdu.edu.cn/showproblem.php?pid=1695
给出a b c d k 在 [a,b] [c,d]内各找一个数,使得gcd(x,y) == k,也就是说 gcd(x / k, y / k) == 1,所以就是在 [1,b / k] [1, d / k]中找互质的对数。容斥原理和欧拉函数的应用,首先在打印素数的同时求出每个数的欧拉函数值,对于[1,b]内的数直接用欧拉数组求互质的对数,对于[b + 1,d]的数用容斥原理求互质对数,首先求出不互质的对数,然后用总的减去不互质的对数。比如说某个数 n ,首先求出 n 的所有因子num, 假设单个因子个数为num1,任意两个因子个数相乘所得因子个数num2,任意三个因子相乘所得因子个数num3 ~~~numn, 那么与n 不互质的个数 tnum = num1 - num2 + num3 - num4 + ~~~~ (-1) ^ (n - 1) numn
View Code
1 typedef __int64 ll; 2 const int N = 100001; 3 int prime[N], phi[N]; 4 int num,tnum; 5 void is_prime() // 求欧拉函数 6 { 7 int i,j; 8 phi[0] = 0, phi[1] = 1; 9 for(i = 2; i < N; i++) 10 { 11 if(!phi[i]) 12 { 13 phi[i] = i - 1; 14 prime[num ++] = i; 15 } 16 for(j = 0; (j < num) && (i * prime[j]) < N; j++) 17 { 18 if(i % prime[j] == 0) 19 { 20 phi[i * prime[j]] = phi[i] * prime[j]; 21 break; 22 } 23 phi[i * prime[j]] = phi[i] * (prime[j] - 1); 24 } 25 } 26 } 27 ll solve(int n,int r) // 容斥定理求互质个数 28 { 29 vector<int>p; 30 for(int i = 2; i * i <= n; i++) 31 { 32 if(n % i == 0) p.push_back(i); 33 while(n % i == 0) n /= i; 34 } 35 if(n > 1) p.push_back(n); 36 ll sum = 0; 37 for(int j = 1; j < (1 << p.size()); j ++) 38 { 39 ll mult = 1, bit = 0; 40 for(int i = 0; i < (int)p.size(); i++) 41 { 42 if(j & (1 << i)) 43 { 44 bit ++; 45 mult *= p[i]; 46 } 47 } 48 ll cur = r / mult; 49 if(bit % 2) sum += cur; 50 else sum -= cur; 51 } 52 return r - sum; 53 } 54 int main() 55 { 56 int a,b,c,d,k; 57 int i; 58 int t,cs = 0; 59 is_prime(); 60 //freopen("data.txt","r",stdin); 61 scanf("%d",&t); 62 while(t--) 63 { 64 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 65 printf("Case %d: ",++cs); 66 if(k == 0) 67 { 68 printf("%d\n",0); 69 continue; 70 } 71 b /= k, d /= k; 72 if(b > d) swap(b,d); 73 ll ans = 0; 74 for(i = 1; i <= b; i++) 75 ans += phi[i]; 76 for(i = b + 1; i <= d; i++) 77 { 78 ans += solve(i,b); 79 } 80 cout<<ans<<endl; 81 //printf("%I64d\n",ans); 82 //printf("%lld\n",ans); 83 } 84 return 0; 85 }