51Nod1594 Gcd and Phi


题目看这里
一个简单的反演题目:

i=1nj=1nϕ(gcd(ϕ(i),ϕ(j)))

首先做一下变换
i=1nj=1nϕ(gcd(ϕ(i),ϕ(j)))
=d=1nϕ(d)f(d)
这里f(d)=i,j[gcd(ϕ(i),ϕ(j))=d]
表示有多少对i,j满足它们的ϕ值的最大公约数为d
我们令F(d)=i,j[d|gcd(ϕ(i),ϕ(j))],就有F(n)=n|df(d)
反演得到f(n)=dF(nd)μ(d)
所以原式可以写成ij<=nϕ(i)F(ij)μ(j)
预处理μ,ϕF的值就可以了

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 2000010 
#define LL long long
using namespace std;
int n,T; long long S;
int w[N>>2],t,phi[N],mu[N],vis[N],c[N];
inline LL F(int x){ return (LL)c[x]c[x]; }
inline void cal(){
scanf("%d",&n); memset(c,S=0,sizeof c);
for(int i=1;i<=n;++i) ++c[phi[i]];
for(int i=1;i<=n;++i)
for(int j=i+i;j<=n;j+=i) c[i]+=c[j];
for(int i=1;i<=n;++i) if(mu[i])
for(int j=1;ij<=n;++j)
S+=(LL)F(ij)mu[i]phi[j];
printf("%lld",S);
}
int main(){
phi[1]=mu[1]=1;
for(int i=2;i<=2000000;++i){
if(!vis[i]){ mu[w[++t]=i]=1; phi[i]=i1; }
for(int j=1,k;(k=iw[j])<=2000000;++j){
vis[k]=1;
if(i%w[j]==0){ phi[k]=phi[i]w[j]; mu[k]=0; break; }
phi[k]=phi[i](w[j]1); mu[k]=mu[i];
} 
}
for(scanf("%d",&T);T;cal());
}

原文地址:https://www.cnblogs.com/Extended-Ash/p/9477078.html