【[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;
}

原文地址:https://www.cnblogs.com/asuldb/p/10207923.html