题目:51nod1040.
题目大意:给定
n
n
n,求
1
1
1~
n
n
n与
n
n
n的最大公约数之和.
1
≤
n
≤
1
0
9
1\leq n\leq 10^9
1≤n≤109.
先将式子写出来:
∑
i
=
1
n
g
c
d
(
i
,
n
)
\sum_{i=1}^{n}gcd(i,n)
i=1∑ngcd(i,n)
考虑从枚举
1
1
1~
n
n
n转变为枚举
n
n
n的因数:
∑
i
=
1
n
g
c
d
(
i
,
n
)
=
∑
d
∣
n
d
∑
i
=
1
n
[
g
c
d
(
i
,
n
)
=
d
]
\sum_{i=1}^{n}gcd(i,n)=\sum_{d|n}d\sum_{i=1}^{n}[gcd(i,n)=d]
i=1∑ngcd(i,n)=d∣n∑di=1∑n[gcd(i,n)=d]
我们设
m
=
n
d
m=\frac{n}{d}
m=dn,那么:
∑
i
=
1
n
g
c
d
(
i
,
n
)
=
∑
d
∣
n
d
∑
i
=
1
m
[
g
c
d
(
i
,
m
)
=
1
]
=
∑
d
∣
n
d
ϕ
(
m
)
=
∑
d
∣
n
d
ϕ
(
n
d
)
\sum_{i=1}^{n}gcd(i,n)\\ =\sum_{d|n}d\sum_{i=1}^{m}[gcd(i,m)=1]\\ =\sum_{d|n}d\phi(m)\\ =\sum_{d|n}d\phi(\frac{n}{d})
i=1∑ngcd(i,n)=d∣n∑di=1∑m[gcd(i,m)=1]=d∣n∑dϕ(m)=d∣n∑dϕ(dn)
由于 n n n很大,我们没有办法直接线性筛筛出 ϕ \phi ϕ值,所以直接根号求解就可以了.
那么时间复杂度为 O ( n 2 ) = O ( n ) O(\sqrt{n}^2)=O(n) O(n2)=O(n),但是这个上界很松,事实上复杂度明显跑不满,所以可以过.
不过一个更正经的做法是,大力分解 n n n的所有质因数,然后计算欧拉函数时直接用 n n n的质因数计算,时间复杂度 O ( n log n ) O(\sqrt{n}\log n) O(nlogn).
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=50;
int n;
int pr[N+9],cp;
void Get_pr(int n){
int now=n;
for (int i=2;i*i<=n;++i)
if (now%i==0)
for (pr[++cp]=i;now%i==0;now/=i);
if (now>1) pr[++cp]=now;
}
int Get_phi(int n){
int res=n;
for (int i=1;i<=cp;++i)
if (n%pr[i]==0) res=res/pr[i]*(pr[i]-1);
return res;
}
LL ans;
Abigail into(){
scanf("%d",&n);
}
Abigail work(){
Get_pr(n);
for (int i=1;i*i<=n;++i)
if (n%i==0){
ans+=(LL)i*Get_phi(n/i);
if (i*i^n) ans+=(LL)n/i*Get_phi(i);
}
}
Abigail outo(){
printf("%lld\n",ans);
}
int main(){
into();
work();
outo();
return 0;
}
本文详细解析了51nod1040题目的解题思路,通过转换枚举方式,利用欧拉函数优化计算过程,最终实现对大规模数值n(1≤n≤10^9)下与n的最大公约数之和的有效求解。
497

被折叠的 条评论
为什么被折叠?



