UVA 11426(欧拉函数)
求 ∑ i = 2 N − 1 ∑ j = i + 1 N g c d ( i , j ) \sum_{i=2}^{N-1}\sum_{j=i+1}^Ngcd(i,j) i=2∑N−1j=i+1∑Ngcd(i,j)
一开始想过用莫比乌斯反演做…然而做不出来。
解:
∑
i
=
1
N
−
1
∑
j
=
i
+
1
N
g
c
d
(
i
,
j
)
=
∑
i
=
2
N
∑
j
=
1
i
−
1
g
c
d
(
i
,
j
)
\sum_{i=1}^{N-1}\sum_{j=i+1}^Ngcd(i,j)=\sum_{i=2}^N\sum_{j=1}^{i-1}gcd(i,j)
i=1∑N−1j=i+1∑Ngcd(i,j)=i=2∑Nj=1∑i−1gcd(i,j)
g
c
d
(
i
,
j
)
=
d
gcd(i,j)=d
gcd(i,j)=d等价于
g
c
d
(
i
d
,
j
d
)
=
1
gcd(\frac{i}{d},\frac{j}{d})=1
gcd(di,dj)=1
既然直接求
g
c
d
(
i
,
j
)
gcd(i,j)
gcd(i,j)比较难,那么我们是否可以求满足
[
g
c
d
(
i
,
j
)
=
=
1
]
[gcd(i,j)==1]
[gcd(i,j)==1]的
(
i
,
j
)
,
j
<
i
(i,j),j<i
(i,j),j<i,这样每对
(
k
∗
i
,
k
∗
j
)
(k*i,k*j)
(k∗i,k∗j)对答案的贡献就是
k
k
k。
因为
j
j
j严格小于
i
i
i,
g
c
d
(
i
,
j
)
=
=
1
gcd(i,j)==1
gcd(i,j)==1的个数就是
ϕ
(
i
)
\phi(i)
ϕ(i)。
现在考虑
k
k
k的取值范围,因为要满足
1
≤
j
<
i
≤
n
1\le j<i\le n
1≤j<i≤n,所以易得
k
k
k的取值范围是
1
≤
k
≤
⌊
n
i
⌋
1\le k\le \lfloor\frac{n}{i}\rfloor
1≤k≤⌊in⌋。
那么每个 i i i对答案的贡献就是 1 + 2 + . . . + ⌊ n i ⌋ 1+2+...+\lfloor\frac{n}{i}\rfloor 1+2+...+⌊in⌋
∑ i = 1 N − 1 ∑ j = i + 1 N g c d ( i , j ) = ∑ i = 2 N ∑ j = 1 i − 1 g c d ( i , j ) = ∑ i = 2 N ϕ ( i ) ( 1 + ⌊ n i ⌋ ) ⌊ n i ⌋ 2 \begin{aligned} \sum_{i=1}^{N-1}\sum_{j=i+1}^Ngcd(i,j)&=\sum_{i=2}^N\sum_{j=1}^{i-1}gcd(i,j)\\ &=\sum_{i=2}^N\phi(i)\frac{(1+\lfloor\frac{n}{i}\rfloor)\lfloor\frac{n}{i}\rfloor}{2} \end{aligned} i=1∑N−1j=i+1∑Ngcd(i,j)=i=2∑Nj=1∑i−1gcd(i,j)=i=2∑Nϕ(i)2(1+⌊in⌋)⌊in⌋
时间复杂度 O ( t n ) + O ( N ) O(tn)+O(N) O(tn)+O(N)
#include<bits/stdc++.h>
using namespace std;
const int max_n=4e6+5;
int prime[max_n];
int vis[max_n];
int cnt=0;
int e[max_n];
void init(void)
{
for(int i=2;i<max_n;i++)
{
if(!vis[i]){
prime[cnt++]=i;
e[i]=i-1;
}
for(int j=0;j<cnt&&i*prime[j]<max_n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0){
e[i*prime[j]]=e[i]*prime[j];
break;
}
e[i*prime[j]]=e[i]*e[prime[j]];
}
}
}
int main(void)
{
int n;
init();
while(~scanf("%d",&n)&&n)
{
long long ans=0,t;
for(int i=2;i<=n;i++)
{
t=n/i;
t=(1+t)*t/2;
ans+=1ll*e[i]*t;
}
printf("%lld\n",ans);
}
}
//10
//100
//200000
//0