GCD
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4291 Accepted Submission(s): 1502
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
Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).
Source
2008 “Sunline Cup” National Invitational Contest
让你求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d)。
没办法,被老师派到了这个数论专题,可怜我初三还没上,对于sigma还是懵逼的,都得硬着头上。
我就是跟着这篇文章学的:点我
讲得很好,适合我这种数学差的蒟蒻。
进入正题
唯一接触过的能用的是容斥原理,欧拉函数
莫比乌斯反演是什么?不知道。于是去学
这题求[1,n],[1,m]gcd为k的对数。而且没有顺序。
转化之后就是[1,n/k],[1,m/k]之间互质的数的个数。
用莫比乌斯反演就很容易求了。
为了去除重复的,去掉一部分就好了
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=1000000; bool check[maxn+10]; int prime[maxn+10]; int U[maxn+10];//表示系数 void get_Mobius() { memset(check,false,sizeof(check)); U[1]=1; int tot=0; for(int i=2;i<=maxn;i++) { if(check[i]==0) { prime[tot++]=i; U[i]=-1;//本身是个质数,1个质数乘积 } for(int j=0;j<tot;j++) { if(i*prime[j]>maxn)break; check[i*prime[j]]=true; if(i%prime[j]==0) { U[i*prime[j]]=0;//除开质数的两种情况 break; } else { U[i*prime[j]]=-U[i];//多了一个数的乘积,与前一个相反 } } } } /* 只要让F(t)=满足gcd(x,y)%t==0的数对个数 f(t)=满足gcd(x,y)=t的数对个数,则F(t)和f(t)就存在莫比乌斯反演的关系了。显然F(t)=(b/t)*(d/t) 因为如果gcd(x,y)=1,则gcd(x?k,y?k)=k,所以我们把b和d同时除以k, 得到的f(1)再去重就是答案。令lim=min(b/k,d/k),就根据我给出的莫比乌斯反演第二个公式, */ int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; int a,b,c,d,k; get_Mobius(); scanf("%d",&T); for(int ii=1;ii<=T;ii++) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0) { printf("0\n"); continue; } b/=k;a/=k; d/=k;c/=k; if(b>d)swap(b,d); long long ans1=0; for(int i=1;i<=b;i++) ans1+=(long long)U[i]*(b/i)*(d/i);//带入 G(n) 的公式 有 F(1) = sigma(U[i]*(a/i)*(b/i)) (1<=i<=N) long long ans2=0; for(int i=1;i<=b;i++) ans2+=(long long)U[i]*(b/i)*(b/i);//相同的数啊如此重复的状况 ans1-=ans2/2; printf("%lld\n",ans1); } return 0; }
by_lmy