题意:[1,a],[1,b] 有多少对GCD(x,y)=k。
分析:约掉k后GCD(x,y)=1,枚举一段区间问题变成,i在[1,b/k]中有多少个与他互质的数。可以用容斥求出,过程:
区间中与i不互质的个数 = (区间中i的每个质因数的倍数个数)-(区间中i的每两个质因数乘积的倍数)+(区间中i的每3个质因数的成绩的倍数个数)-(区间中i的每4个质因数的乘积)+...
然后减去不互质的剩下的就是互质的数。
由于题目中[2,3],[3,2]属于同一对。直接容斥还是会有重复的,我们知道欧拉函数可以求出比i小的且与他互质的数,这样我们就可以求出[1,b],[1,b]
之间的数,然后容斥[1,b][b+1,d]的数就行了。
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 100005
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef __int64 ll;
int read() {
char c;
int ans=0,f=1;c=getchar();
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {ans=ans*10+c-'0';c=getchar();}
return ans*f;
}
ll eular[Mn];
int s[Mn][20],tot;
void Eular() {
eular[1]=1;
for(int i=2;i<=Mn;i++) {
if(!eular[i])
for(int j=i;j<=Mn;j+=i) {
if(!eular[j]) eular[j]=j;
eular[j]=eular[j]*(i-1)/i;
s[j][++s[j][0]]=i;
}
eular[i]+=eular[i-1];
}
}
ll dfs(int pos,int v,int x) {
ll re=0;
for(int i=pos;i<=s[x][0];i++) {
re+=v/s[x][i]-dfs(i+1,v/s[x][i],x);
}
return re;
}
int main() {
Eular();
int t=read();
for(int cas=1;cas<=t;cas++) {
int a=read(),b=read(),c=read(),d=read(),k=read();
if(!k) {
printf("Case %d: 0\n",cas);
continue;
}
if(b>d) swap(b,d);
b/=k;d/=k;
ll sum=eular[b];
for(int i=b+1;i<=d;i++) {
sum+=b-dfs(1,b,i);
}
printf("Case %d: %I64d\n",cas,sum);
}
return 0;
}