GCD
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2474 Accepted Submission(s): 902
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.
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.
2 1 3 1 5 1 1 11014 1 14409 9
Case 1: 9 Case 2: 736427HintFor 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).
//本题没想到好的方法,借用了某牛的思路才写过的!
//分析:题目是要求a<=x<=b,c<=y<=d(其中a,c题目中已经说了必为1),中有多少对(x,y)(无序的)满足GCD(x,y)=k,那么可以转化成求(x,y)分别在区间1<=x<=b/k,1<=y<=d/k中有多少对满足GCD(x,y)=1; 转换b/=k,d/=k,之后,假设b<=d,那么我们可以分两步来求值:
1、求[1,b]与[1,b]之间有多少对数互质,显然就是phi[1]+phi[2]+...phi[b]即可,用线性求欧拉函数的算法即可!
2\求[1,b]与[b+1,d]之间有多少对数互质,可以先求出有多少对数不互质,然后减去即可! 针对于区间[b+1,d]中得某一个数n求区间[1,b]中有多少个数与他不互质(即有公约数)那么可以用容斥原理较好的解决!
两步求值之和即为题意所求!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define maxn 100005
int phi[maxn],x[maxn],cnt[1005];
void Init()
{
int i,j;
memset(x,0,sizeof(x));
x[0]=x[1]=1;
for(i=1;i<maxn;i++)
phi[i]=i;
for(i=2;i<maxn;i++)
{
if(!x[i])
{
phi[i]=i-1;
for(j=i*2;j<maxn;j+=i)
{
x[j]=1;
phi[j]=phi[j]/i*(i-1);
}
}
}
}
LL Imco_prime(int n,int m)
{
int i,j,t=0;
for(i=2;i*i<=n;i++)
{
if(n&&n%i==0)
{
cnt[t++]=i;
while(n&&n%i==0)
n/=i;
}
}
if(n>1)
cnt[t++]=n;
LL ans=0,tmp,flag;
for(i=1;i<(1<<t);i++)
{
tmp=1,flag=0;
for(j=0;j<t;j++)
if(i&(1<<j))
flag++,tmp*=cnt[j];
if(flag&1)
ans+=m/tmp;
else
ans-=m/tmp;
}
return ans;
}
int main()
{
Init();
int T,t=0,a,b,c,d,k,i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
if(k==0)
{
printf("Case %d: 0\n",++t);
continue;
}
b/=k,d/=k;
if(b>d)
swap(b,d);
LL ans=0,tmp=(LL)b*(d-b); //细节
for(i=1;i<=b;i++)
ans+=phi[i];
for(i=b+1;i<=d;i++)
tmp-=Imco_prime(i,b);
printf("Case %d: %I64d\n",++t,ans+tmp);
}
return 0;
}