链接:戳这里
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).
题意:给出[1,b]和[1,d]两个区间,分别在区间内选x,y使gcd(x,y)==k 求满足的x,y的的对数
思路:当然了 gcd(x/k,y/k)==1 嗯 显然就是莫比乌斯反演了 具体的看上一篇博客把
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<iomanip> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 100010 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 using namespace std; int a,b,c,d,k; int mu[MAX],prime[MAX],vis[MAX],cnt; void Moblus(){ cnt=0; mu[1]=1; mst(vis,0); for(int i=2;i<=MAX;i++){ if(!vis[i]){ mu[i]=-1; prime[++cnt]=i; } for(int j=1;j<=cnt;j++){ if(i*prime[j]>MAX) break; vis[i*prime[j]]=1; if(i%prime[j]==0){ mu[i*prime[j]]=0; break; } else mu[i*prime[j]]=-mu[i]; } } } int main(){ Moblus(); int T; scanf("%d",&T); for(int cas=1;cas<=T;cas++){ scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("Case %d: ",cas); if(k==0){ cout<<0<<endl; continue; } if(b>d) swap(b,d); b/=k;d/=k; ll ans1=0,ans2=0; for(int i=1;i<=b;i++){ ans1+=(ll)mu[i]*(b/i)*(d/i); } for(int i=1;i<=b;i++){ ans2+=(ll)mu[i]*(b/i)*(b/i); } printf("%I64d\n",ans1-(ans2/2)); } return 0; }