【[SDOi2012]Longge的问题】

\(\sum_{i=1}^ngcd(i,n)\)

考虑枚举\(gcd\),现在答案变成这样

\(\sum_{d|n}d*f(d)\)

\(f(d)=\sum_{i=1}^n [gcd(i,n)==d]\)

考虑一下\(f(d)\)如何求

显然\(f(d)=\varphi(n/d)\)

因为所有与\(n/d\)互质的数乘上\(d\)就是和\(n\)互质的数了

所有答案就是\(\sum_{d|n}d*\varphi(n/d)\)

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define re register
#define LL long long
#define maxn 65580
inline int read()
{
	char c=getchar();
	int x=0;
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9')
		x=(x<<3)+(x<<1)+c-48,c=getchar();
	return x;
}
int phi[maxn],p[maxn],f[maxn];
LL n,ans;
int U;
inline LL solve(LL x)
{
	if(x<=U) return phi[x];
	LL now=1;
	for(re int i=1;i<=p[0];i++)
	if(x%p[i]==0)
	{
		LL tot=1;
		while(x%p[i]==0) tot*=p[i],x/=p[i];
		now*=(p[i]-1)*(tot/p[i]);
		if(x==1) break;
	}
	if(x!=1) now*=(x-1);
	return now;
}
int main()
{
	scanf("%lld",&n);
	f[1]=1,phi[1]=1;
	U=std::sqrt(n);
	for(re int i=2;i<=U;i++)
	{
		if(!f[i]) p[++p[0]]=i,phi[i]=i-1;
		for(re int j=1;j<=p[0]&&p[j]*i<=U;j++)
		{
			f[p[j]*i]=1;
			if(i%p[j]==0)
			{
				phi[p[j]*i]=phi[i]*p[j];
				break;
			}
			phi[p[j]*i]=phi[i]*(p[j]-1);
		}
	}
	for(re LL i=1;i*i<=n;i++)
	if(n%i==0)
	{
		ans+=i*solve(n/i);
		if(n/i!=i) ans+=(n/i)*solve(i);
	}
	std::cout<<ans;
	return 0;
}

posted @ 2019-01-02 12:23  asuldb  阅读(140)  评论(0编辑  收藏  举报