题目描述
传送门
题目大意:
∑i=1nlcm(i,n)
题解
又要化式子啦,开心。
∑i=1nlcm(i,n)
∑d=1n∑i=1ni∗nd[gcd(i,n)=d]
n∑d|n∑i=1ndi∗[gcd(i,nd)=1]
设 g(n)=∑ni=1i∗[gcd(i,n)=1] ,那么上式就是
n∑d|ng(nd)
考虑怎么求 g(n)
g(n)=∑i=1ni∗[gcd(i,n)=1]
∑i=1ni∑d|(i,n)μ(d)
∑d|nd∗μ(d)∑i=1ndi
∑d|nd∗μ(d)(1+nd)nd/2
n2∑d|n(μ(d)+nd∗μ(d))
n2∑d|nμ(d)+∑d|nnd∗μ(d)
因为 ∑d|nφ(d)=id(n) ,根据莫比乌斯反演的公式 F(n)=∑d|nf(d),f(n)=∑d|nF(d)∗μ(nd) ,所以 ∑d|nnd∗μ(d)=φ(n) .
∑d|nμ(d)=[n=1] ,所以上面的式子在n>1时, g(n)=n∗φ(n)2
这个与n互质数的和可以当做结论记住。
n∑d|ng(nd)
,这个东西可以用艾氏筛法预处理,然后
O(1)
查询。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 1000000
#define LL long long
using namespace std;
int T,n,pd[N+3],prime[N+3],f[N+3],phi[N+3];
LL g[N+3],ans[N+3];
void init()
{
for (int i=2;i<=N;i++) {
if (!pd[i]) {
prime[++prime[0]]=i;
phi[i]=i-1;
}
for (int j=1;j<=prime[0];j++) {
if (i*prime[j]>N) break;
pd[i*prime[j]]=1;
if (i%prime[j]==0) {
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
g[1]=1;
for (int i=2;i<=N;i++) g[i]=(LL)i*phi[i]/2;
for (int i=1;i<=N;i++)
for (int j=i;j<=N;j+=i) ans[j]+=g[i];
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&T);
init();
while (T--) {
scanf("%d",&n);
printf("%lld\n",n*ans[n]);
}
}