题目大意
求 ∑ i = 1 n g c d ( i , n ) \sum_{i=1}^{n}\ gcd(i,n) ∑i=1n gcd(i,n)
解题分析
注意,所有gcd(x,n)最后都是n的因数。所以可以对因数分类,设
f
(
i
)
f(i)
f(i)为
g
c
d
(
x
,
n
)
=
=
i
且
i
<
n
gcd(x,n)==i且i<n
gcd(x,n)==i且i<n的正整数x,则
a
n
s
=
∑
i
∗
f
[
i
]
∣
i
为
n
的
因
数
ans=\sum\ i*f[i]|i为n的因数
ans=∑ i∗f[i]∣i为n的因数
如果 g c d ( x , n ) = i gcd(x,n)=i gcd(x,n)=i,则 g c d ( x / i , n / i ) = 1 gcd(x/i,n/i)=1 gcd(x/i,n/i)=1,gcd()=1就想到了欧拉函数,所以最后 f [ i ] = φ ( n / i ) f[i]=\varphi(n/i) f[i]=φ(n/i)
复杂度:
时间:
O
(
n
)
O(\sqrt{n})
O(n);
空间:
O
(
1
)
O(1)
O(1);
#include<cmath>
#include<cstdio>
#define LL long long
using namespace std;
int n,S,p[10005];
LL ans;
int getp(int x){
int sum=x; for (int i=2,S=sqrt(x);i<=S;i++) if (x%i==0) {sum=sum/i*(i-1); while (x%i==0) x/=i;}
if (x>1) sum=sum/x*(x-1); return sum;
}
int main()
{
freopen("gcda.in","r",stdin);
freopen("gcda.out","w",stdout);
scanf("%d",&n); S=sqrt(n); ans=0;
for (int i=1;i<=S;i++)
if (n%i==0){
int t=n/i;ans+=(LL)i*getp(t);
if (i!=t) ans+=(LL)t*getp(i);
}
printf("%lld",ans);
return 0;
}