背景:
推了好久的式子,发现一开始错了。
题目传送门:
https://www.luogu.org/problem/P1891
∑
i
=
1
n
lcm
(
i
,
n
)
\sum_{i=1}^{n}\text{lcm}(i,n)
i=1∑nlcm(i,n)
= ∑ i = 1 n n ⋅ i gcd ( i , n ) =\sum_{i=1}^{n}\frac{n\cdot i}{\gcd(i,n)} =i=1∑ngcd(i,n)n⋅i
= n ∑ k = 1 n ∑ i = 1 n i k [ gcd ( i , n ) = k ] =n\sum_{k=1}^{n}\sum_{i=1}^{n}\frac{i}{k}[\gcd(i,n)=k] =nk=1∑ni=1∑nki[gcd(i,n)=k]
显然有
k
∣
n
k|n
k∣n,所以:
=
n
∑
k
∣
n
∑
i
=
1
n
i
k
[
gcd
(
i
,
n
)
=
k
]
=n\sum_{k|n}\sum_{i=1}^{n}\frac{i}{k}[\gcd(i,n)=k]
=nk∣n∑i=1∑nki[gcd(i,n)=k]
= n ∑ k ∣ n ∑ i = 1 n k i k [ gcd ( i k , n k ) = 1 ] =n\sum_{k|n}\sum_{i=1}^{\frac{n}{k}}\frac{i}{k}[\gcd(\frac{i}{k},\frac{n}{k})=1] =nk∣n∑i=1∑knki[gcd(ki,kn)=1]
= n ∑ k ∣ n ∑ i = 1 k i [ gcd ( i , n k ) = 1 ] =n\sum_{k|n}\sum_{i=1}^{k}i[\gcd(i,\frac{n}{k})=1] =nk∣n∑i=1∑ki[gcd(i,kn)=1]
令
d
=
n
k
d=\frac{n}{k}
d=kn,有:
=
n
∑
d
∣
n
∑
i
=
1
d
i
[
gcd
(
i
,
n
)
=
1
]
=n\sum_{d|n}\sum_{i=1}^{d}i[\gcd(i,n)=1]
=nd∣n∑i=1∑di[gcd(i,n)=1]
考虑
∑
i
=
1
d
i
[
gcd
(
i
,
n
)
=
1
]
=
d
⋅
ϕ
d
2
\sum_{i=1}^{d}i[\gcd(i,n)=1]=\frac{d\cdot\phi_d}2{}
∑i=1di[gcd(i,n)=1]=2d⋅ϕd,
Θ
(
n
log
n
)
\Theta(n\log n)
Θ(nlogn)预处理即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int n;
int prime[1000010],phi[1000010];
LL ans[1000010];
void init(int ma)
{
int t=0;
phi[1]=1;
for(int i=2;i<=ma;i++)
{
if(!phi[i]) prime[++t]=i,phi[i]=i-1;
for(int j=1;j<=t&&i*prime[j]<=ma;j++)
{
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
for(int i=1;i<=ma;i++)
for(int j=1;i*j<=ma;j++)
ans[i*j]+=(((LL)phi[j]*j+1)>>1);
}
int main()
{
int T;
init(1000000);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%lld\n",ans[n]*n);
}
}