Uva 11426 GCD - Extreme (II)
题目链接:GCD - Extreme (II)
题目大意:emm,其实没有题目大意,就是求
我们考虑设
f
(
n
)
=
Σ
(
g
c
d
(
n
,
i
)
)
,
(
i
=
1
…
n
−
1
)
f(n)=\Sigma(gcd(n,i)),(i=1…n-1)
f(n)=Σ(gcd(n,i)),(i=1…n−1)
答案就是从f(2)到f(n)的和,接下来我们考虑如何求f(n)。
设
g
(
n
,
i
)
g(n,i)
g(n,i)为
g
c
d
(
x
,
n
)
=
i
,
x
<
n
gcd(x,n)=i,x<n
gcd(x,n)=i,x<n的
x
x
x的个数,则
f
(
n
)
=
Σ
(
i
∗
g
(
n
,
i
)
)
(
i
∣
n
)
f(n)=\Sigma(i*g(n,i))(i|n)
f(n)=Σ(i∗g(n,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所以就可以把求
g
(
i
)
g(i)
g(i)的问题转化为求
ϕ
(
i
)
\phi(i)
ϕ(i),这样就可以直接套欧拉函数了。但是如果直接去找n的因子,时间复杂度较高,所以我们逆过来对于每个i去枚举他的倍数,这时的时间复杂度变的和埃筛差不多。
最后附上完整代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define MXN 4000000
#define LL long long
using namespace std;
int n,phi[MXN+10],f[MXN+10];
LL S[MXN+10];
void phi_table(){
phi[1]=1;
for(int i=2;i<=MXN;i++)
if(!phi[i])
for(int j=i;j<=MXN;j+=i){
if(!phi[j])phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
int main()
{
phi_table();
for(int i=1;i<=MXN;i++)
for(int j=i*2;j<=MXN;j+=i)
f[j]+=i*phi[j/i];
S[2]=f[2];
for(int i=3;i<=MXN;i++)
S[i]=S[i-1]+f[i];
while(scanf("%d",&n)){
if(n==0)break;
printf("%lld\n",S[n]);
}
return 0;
}