GCD
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9696 Accepted Submission(s): 3623
Problem Description
Given
5 integers: a, b, c, d, k, you‘re to find x in a...b, y in c...d that
GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y.
Since the number of choices may be very large, you‘re only required to
output the total number of different number pairs.
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.
Yoiu can assume that a = c = 1 in all test cases.
Input
The
input consists of several test cases. The first line of the input is
the number of the cases. There are no more than 3,000 cases.
Each
case contains five integers: a, b, c, d, k, 0 < a <= b <=
100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as
described above.
Output
For each test case, print the number of choices. Use the format in the example.
Sample Input
2
1 3 1 5 1
1 11014 1 14409 9
Sample Output
Case 1: 9
Case 2: 736427
思路:容斥+欧拉函数;
n,m最大公约数为k,那么就转换成找(n/k,m/k)互质的对数;那么这个会想到欧拉函数,但是欧拉函数可以解决,n,m相等的情况,当n,m不等的时候
那么直接用容斥跑(1,min(n,m))在(1,max(m,n))中互质的数的个数,最后再减掉oula[min(n,m)],这是重复的,然后再加上1也就是(1,1)是没重,但在oula[]中减了
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<stdlib.h> 6 #include<queue> 7 #include<math.h> 8 #include<vector> 9 using namespace std; 10 typedef long long LL; 11 bool prime[100005]; 12 int ans[100005]; 13 int flag[100005]; 14 int fen[100]; 15 int d[100005]; 16 LL oula[100005]; 17 int slove(int n,int m); 18 int main(void) 19 { 20 int i,j,k; 21 fill(ans,ans+100005,1); 22 fill(d,d+100005,1); 23 int c=0; 24 for(i=0; i<=100000; i++)oula[i]=i; 25 for(i=2; i<=100000; i++) 26 { 27 if(!prime[i]) 28 { 29 for(j=2; (i*j)<=100000; j++) 30 { 31 prime[i*j]=true; 32 ans[i*j]*=i; 33 d[i*j]=i; 34 } 35 } 36 } 37 oula[0]; 38 oula[1]=1; 39 for(i=2; i<=100000; i++) 40 { 41 if(!prime[i]) 42 { 43 ans[i]*=i; 44 d[i]=i; 45 for(j=1; (LL)i*(LL)j<=100000; j++) 46 { 47 oula[i*j]/=i; 48 oula[i*j]*=(i-1); 49 } 50 } 51 } 52 int s; 53 scanf("%d",&k); 54 LL sum=0; 55 int n,m; 56 for(i=2; i<=100000; i++)oula[i]+=oula[i-1]; 57 for(s=1; s<=k; s++) 58 { 59 sum=0; 60 int xx,yy,vv; 61 memset(flag,-1,sizeof(flag)); 62 scanf("%d %d %d %d %d",&xx,&n,&yy,&m,&vv); 63 if(vv>n||vv>m|vv==0) 64 { 65 printf("Case %d: ",s); 66 printf("0\n"); 67 } 68 else 69 { 70 if(n>m) 71 { 72 swap(n,m); 73 } 74 n/=vv; 75 m/=vv; 76 sum=0; 77 for(i=1; i<=n; i++) 78 { 79 if(flag[ans[i]]!=-1) 80 { 81 sum+=flag[ans[i]]; 82 } 83 else 84 { 85 flag[ans[i]]=slove(i,m); 86 sum+=flag[ans[i]]; 87 } 88 } 89 //printf("%lld %lld\n",oula[5],sum); 90 printf("Case %d: %lld\n",s,sum-oula[min(n,m)]+1); 91 } 92 } 93 return 0; 94 } 95 int slove(int n,int m) 96 { 97 int i,j,k; 98 int nn=n; 99 int cnt=0; 100 while(n>1) 101 { 102 fen[cnt++]=d[n]; 103 n/=d[n]; 104 } 105 int cc=1<<cnt; 106 LL sum=0; 107 int sum1=0; 108 for(i=1; i<cc; i++) 109 { 110 int ck=0; 111 int ak=1; 112 for(j=0; j<cnt; j++) 113 { 114 if(i&(1<<j)) 115 { 116 ak*=fen[j]; 117 ck++; 118 } 119 } 120 if(ck%2) 121 { 122 sum+=m/ak; 123 } 124 else sum-=m/ak; 125 } 126 return m-sum; 127 }