hdu 1695 GCD (莫比乌斯反演)
题意:给你两个区间,区间的左端点式1,然后让你求有多少对数来自两个区间,然后他们的GCD为k;
思路:我们找两个数x,y的GCD为k,分别除以k后,相当于找x,y互质的个数,
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long LL; int mu[1<<20]; LL n; bool check[1<<20]; int prime[1<<20]; void Moblus() { memset(check,false,sizeof(check)); mu[1]=1; int tot=0; for(int i=2;i<=(1<<20);i++){ if(!check[i]){ prime[tot++]=i; mu[i]=-1; } for(int j=0;j<tot;j++){ if(i*prime[j]>(1<<20)) break; check[i*prime[j]]=true; if(i%prime[j]==0){ mu[i*prime[j]]=0;break; } else{ mu[i*prime[j]]=-mu[i]; } } } } int main() { int T; scanf("%d",&T); Moblus(); int cas=1; while(T--){ int a,b,c,d,k; scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0){ printf("Case %d: 0\n",cas++);continue; } if(b>d)swap(b,d); b/=k;d/=k; LL ans=0; for(int i=1;i<=b;i++){ ans+=(LL)mu[i]*(b/i)*(d/i); } LL cnt=0; for(int i=1;i<=b;i++){ cnt+=(LL)mu[i]*(b/i)*(b/i); } printf("Case %d: %lld\n",cas++,ans-cnt/2); } return 0; }