式子化简:
∑
i
=
1
N
∑
j
=
1
N
m
a
x
(
i
,
j
)
∗
σ
(
i
∗
j
)
\sum_{i=1}^{N}\sum_{j=1}^{N}max(i,j)*\sigma(i*j)
i=1∑Nj=1∑Nmax(i,j)∗σ(i∗j)
枚举
m
a
x
(
i
,
j
)
max(i,j)
max(i,j) 得到:
2
∗
(
∑
i
=
1
N
i
∑
i
=
1
j
σ
(
i
∗
j
)
)
−
∑
i
=
1
N
i
∗
σ
(
i
2
)
2*(\sum_{i=1}^{N}i\sum_{i=1}^{j}\sigma(i*j)) -\sum_{i=1}^{N}i*\sigma(i^2)
2∗(i=1∑Nii=1∑jσ(i∗j))−i=1∑Ni∗σ(i2)
记上式大括号里的式子为 F ( N ) F(N) F(N),减号后面的式子为 G ( N ) G(N) G(N)
换个枚举方式方便预处理:
枚举
i
i
i 对
k
k
k 做贡献然后前缀和一下就可以了。
G
(
N
)
G(N)
G(N) 是类似的处理方式,将
σ
(
i
2
)
\sigma(i^2)
σ(i2)展开为
∑
x
∣
i
∑
y
∣
i
[
(
x
,
y
)
=
=
1
]
x
∗
i
/
y
\sum_{x|i}\sum_{y|i}[(x,y)==1]x*i/y
∑x∣i∑y∣i[(x,y)==1]x∗i/y,最终可以得到:
code
#include<bits/stdc++.h>
#define maxn 1000005
using namespace std;
const int mod = 1e9+7;
int T,n,p[maxn/8],mu[maxn],sig[maxn],mps[maxn],ss[maxn],F[maxn],G[maxn];
bool v[maxn];
void Prime(const int N){
mu[1]=sig[1]=1;int m=0;
for(int i=2;i<=N;i++){
if(!v[i]) p[++m]=i,mu[i]=-1,sig[i]=mps[i]=i+1;
for(int j=1,k;j<=m&&((k=i*p[j])<=N);j++){
v[k]=1;
if(i%p[j]==0) {sig[k]=sig[i]/mps[i]*(mps[k]=mps[i]*p[j]+1);break;}
sig[k]=sig[i]*(mps[k]=p[j]+1),mu[k]=-mu[i];
}
}
for(int i=1;i<=N;i++) ss[i]=(ss[i-1]+sig[i])%mod;
for(int i=1;i<=N;i++)
for(int j=1,k=i;k<=N;k+=i,j++) if(mu[j]){
int tmp=1ll*mu[j]*j*j%mod*i%mod*sig[i]%mod;
F[k]=(F[k]+1ll*tmp*ss[i])%mod,
G[k]=(G[k]+1ll*tmp*sig[i])%mod;
}
for(int i=1;i<=N;i++) F[i]=(F[i]+F[i-1])%mod,G[i]=(G[i]+G[i-1])%mod;
}
int main()
{
Prime(maxn-5);
scanf("%d",&T);
for(int t=1;t<=T;t++) scanf("%d",&n),printf("Case #%d: %d\n",t,(2ll*F[n]-G[n]+3ll*mod)%mod);
}