Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4272 Accepted Submission(s): 1492
题意: 在1~a, 1~b中挑出(x,y)满足gcd(x,y) = k , 求(x,y) 的对数 , a,b<=10^5
思路: gcd(x, y) == k 说明x,y都能被k整除, 但是能被k整除的未必gcd=k , 必须还要满足
互质关系. 问题就转化为了求1~a/k 和 1~b/k间互质对数的问题
可以把a设置为小的那个数, 那么以y>x来保持唯一性(题目要求, 比如[1,3] = [3,1] )
接下来份两种情况:
1. y <= a , 那么对数就是 1~a的欧拉函数的累计和(容易想到)
2. y >= a , 这个时候欧拉函数不能用了,怎么做? 可以用容斥原理,把y与1~a互质对数问题转换为
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/8/19 22:08:43 4 File Name :F:\2013ACM练习\专题学习\数学\HDU\HDU1695GCD.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 const int MAXN = 10000; 22 int prime[MAXN+1]; 23 void getPrime() 24 { 25 memset(prime,0,sizeof(prime)); 26 for(int i = 2;i <= MAXN;i++) 27 { 28 if(!prime[i])prime[++prime[0]] = i; 29 for(int j = 1;j <= prime[0] && prime[j] <= MAXN/i;j++) 30 { 31 prime[prime[j]*i] = 1; 32 if(i%prime[j] == 0)break; 33 } 34 } 35 } 36 long long factor[100][2]; 37 int fatCnt; 38 int getFactors(long long x) 39 { 40 fatCnt = 0; 41 long long tmp = x; 42 for(int i = 1; prime[i] <= tmp/prime[i];i++) 43 { 44 factor[fatCnt][1] = 0; 45 if(tmp%prime[i] == 0) 46 { 47 factor[fatCnt][0] = prime[i]; 48 while(tmp%prime[i] == 0) 49 { 50 factor[fatCnt][1]++; 51 tmp /= prime[i]; 52 } 53 fatCnt++; 54 } 55 } 56 if(tmp != 1) 57 { 58 factor[fatCnt][0] = tmp; 59 factor[fatCnt++][1] = 1; 60 } 61 return fatCnt; 62 } 63 int euler[100010]; 64 void getEuler() 65 { 66 memset(euler,0,sizeof(euler)); 67 euler[1] = 1; 68 for(int i = 2;i <= 100000;i++) 69 if(!euler[i]) 70 for(int j = i; j <= 100000;j += i) 71 { 72 if(!euler[j]) 73 euler[j] = j; 74 euler[j] = euler[j]/i*(i-1); 75 } 76 } 77 int calc(int n,int m)//n < m,求1-n内和m互质的数的个数 78 { 79 getFactors(m); 80 int ans = 0; 81 for(int i = 1;i < (1<<fatCnt);i++) 82 { 83 int cnt = 0; 84 int tmp = 1; 85 for(int j = 0;j < fatCnt;j++) 86 if(i&(1<<j)) 87 { 88 cnt++; 89 tmp *= factor[j][0]; 90 } 91 if(cnt&1)ans += n/tmp; 92 else ans -= n/tmp; 93 } 94 return n - ans; 95 } 96 int main() 97 { 98 //freopen("in.txt","r",stdin); 99 //freopen("out.txt","w",stdout); 100 getPrime(); 101 int a,b,c,d; 102 int T; 103 int k; 104 scanf("%d",&T); 105 int iCase = 0; 106 getEuler(); 107 while(T--) 108 { 109 iCase++; 110 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 111 if(k == 0 || k > b || k > d) 112 { 113 printf("Case %d: 0\n",iCase); 114 continue; 115 } 116 if(b > d)swap(b,d); 117 b /= k; 118 d /= k; 119 long long ans = 0; 120 for(int i = 1;i <= b;i++) 121 ans += euler[i]; 122 for(int i = b+1;i <= d;i++) 123 ans += calc(b,i); 124 printf("Case %d: %I64d\n",iCase,ans); 125 } 126 127 return 0; 128 }