数论蒟蒻来写题解啦因为太弱所以只敢写在这里。
题面:
Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。
n
≤
2
32
n\leq 2^{32}
n≤232
思路:暴力枚举是不可能的,但是发现 n n n是一直存在的,那么答案只有可能是 n n n的约数,所以考虑枚举答案统计贡献。
那么我们把问题变成了
a
n
s
=
∑
d
∣
n
d
×
∑
i
=
1
n
[
g
c
d
(
i
,
n
)
=
d
]
\qquad \qquad ans = \sum\limits_{d|n}d\times \sum\limits_{i=1}^{n}[gcd(i,n)=d]
ans=d∣n∑d×i=1∑n[gcd(i,n)=d]
一起除个
d
d
d
a
n
s
=
∑
d
∣
n
d
×
∑
i
=
1
n
[
g
c
d
(
i
d
,
n
d
)
=
1
]
\quad \qquad \qquad ans= \sum\limits_{d|n}d\times \sum\limits_{i=1}^{n}[gcd(\frac{i}{d},\frac{n}{d})=1]
ans=d∣n∑d×i=1∑n[gcd(di,dn)=1]
把
i
i
i的那个除号提出来
a
n
s
=
∑
d
∣
n
d
×
∑
i
=
1
n
d
[
g
c
d
(
i
,
n
d
)
=
1
]
\qquad \qquad \quad ans= \sum\limits_{d|n}d\times \sum\limits_{i=1}^{\frac{n}{d}}[gcd(i,\frac{n}{d})=1]
ans=d∣n∑d×i=1∑dn[gcd(i,dn)=1]
应该很好理解吧。
然后我们发现:这不就是欧拉函数吗???
a
n
s
=
∑
d
∣
n
d
×
ϕ
(
n
d
)
ans=\sum\limits_{d|n}d\times \phi(\frac{n}{d})
ans=d∣n∑d×ϕ(dn)
然后复杂度不会用 O O O写,大概就是 ( ∑ d ∣ n d ) (\sum\limits_{d|n}\sqrt{d}) (d∣n∑d)+ n \sqrt{n} n
实际上跑得飞快。
如果你还想优化,可以预处理 n \sqrt{n} n以内的质数,优化 d \sqrt{d} d的那部分复杂度。
c o d e code code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int euler(int a){
int ans=a;
for(int i=2;i*i<=a;++i)
if(a%i==0){
ans=ans/i*(i-1);
while(a%i==0)a/=i;
}
if(a!=1)ans=ans/a*(a-1);
return ans;
}
int n,ans;
signed main(){
scanf("%lld",&n);
for(int i=1;i*i<=n;++i)
if(n%i==0){
ans+=i*euler(n/i);
if(i!=n/i) ans+=(n/i)*euler(i);
}
printf("%lld",ans);
return 0;
}