莫比烏斯反演模板題。html
假設要求\(gcd(x,y)==k\)的數對的對數,即\(gcd(\frac{x}{k},\frac{y}{k})==1\)的數對的對數。ios
(如下\(x,y,n\)均視爲除以\(k\)以後)git
設\(f[i]\)爲\(gcd(x,y)==i\)的對數,\(g[i]\)爲\(gcd(x,y)==xi\)的對數,其中\(x\in Z\)。spa
顯然,\(g[i]=(n/i)*(n/i)\)code
有\(g[x]=\sum\limits_{x|d}^nf[d]\),而後,你驚喜地發現,這就是莫比烏斯反演的模板。htm
因此\(f[x]=\sum\limits_{x|d}^n\mu(\frac{d}{x})*g[d]\),直接計算便可。blog
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #include<iomanip> #include<cstdlib> #define MAXN 0x7fffffff typedef long long LL; const int N=10000005; using namespace std; inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;} int mu[N],prime[N]; bool vis[N]; int main(){ int n=Getint(); mu[1]=1; for(int i=2;i<n;i++){ if(!vis[i])prime[++prime[0]]=i,mu[i]=-1; for(int j=1;j<=prime[0]&&i*prime[j]<n;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0)break; mu[i*prime[j]]=-mu[i]; } } LL ans=0; for(int i=1;i<=prime[0];i++) for(int j=1;j*prime[i]<=n;j++) ans+=(LL)mu[j]*(n/j/prime[i])*(n/j/prime[i]); cout<<ans; return 0; }
P.Sip
增強版:【BZOJ2820】YY的GCDget