分析
首先,我们设定在
k
k
k 意义下的
x
x
x 和
y
y
y,枚举它们。发现每一个贡献都是
⌊
n
max
(
x
,
y
)
⌋
2
\lfloor\frac{n}{\max(x,y)}\rfloor^2
⌊max(x,y)n⌋2。设只需要计算一边,我们需要求:
∑
x
=
2
n
∑
y
=
1
i
−
1
⌊
n
max
(
x
,
y
)
⌋
2
\sum_{x=2}^{n}\sum_{y=1}^{i-1}\lfloor\frac{n}{\max(x,y)}\rfloor^2
x=2∑ny=1∑i−1⌊max(x,y)n⌋2
以上式子还算重了很多,考虑限制看到的第一个点计算贡献,即多加一个条件
[
gcd
(
x
,
y
)
=
1
]
[\gcd(x,y)=1]
[gcd(x,y)=1]。
∑
x
=
2
n
∑
y
=
1
x
−
1
[
gcd
(
x
,
y
)
=
1
]
⌊
n
x
⌋
2
\sum_{x=2}^{n}\sum_{y=1}^{x-1}[\gcd(x,y)=1]\lfloor\frac{n}{x}\rfloor^2
x=2∑ny=1∑x−1[gcd(x,y)=1]⌊xn⌋2
把第二个
∑
\sum
∑ 变成欧拉函数的形式,得:
∑
x
=
2
n
φ
(
x
)
⌊
n
x
⌋
2
\sum_{x=2}^{n}\varphi(x)\lfloor\frac{n}{x}\rfloor^2
x=2∑nφ(x)⌊xn⌋2
最后的答案不是这一个。由于只计算了一边,所以要乘以
2
2
2。而且中间的对角线也需要算进去,贡献为
n
×
n
n\times n
n×n。
由于 n n n 可以达到 2 31 − 1 2^{31}-1 231−1,所以欧拉函数需要使用杜教筛优化,整个式子的计算需要使用数论分块。
代码
#include<bits/stdc++.h>
#define MAXN 1664511
#define MOD 1000000007
using namespace std;
typedef long long ll;
vector<int> prim;
bool flag[MAXN];
int phi[MAXN];
ll pre[MAXN];
map<int,ll> mp;
inline void prework(){
phi[1]=1;
for(int i=2;i<MAXN;++i){
if(!flag[i]){
prim.push_back(i);
phi[i]=i-1;
}
for(int j=0;j<prim.size()&&i*prim[j]<MAXN;++j){
flag[i*prim[j]]=true;
if(i%prim[j]){
phi[i*prim[j]]=phi[i]*(prim[j]-1);
}else{
phi[i*prim[j]]=phi[i]*prim[j];
break;
}
}
}
for(int i=1;i<MAXN;++i){
pre[i]=(pre[i-1]+phi[i])%MOD;
}
}
ll varphi(int n){
if(n<MAXN){
return pre[n];
}
if(mp[n]){
return mp[n];
}
ll res=1ll*n*(n+1ll)>>1ll;
for(int l=2,r=0;l<=n;l=r+1){
r=n/(n/l);
(res-=varphi(n/l)*1ll*(r-l+1)%MOD)%=MOD;
}
return mp[n]=(res%MOD+MOD)%MOD;
}
int main(){
prework();
int n;
scanf("%d",&n);
ll res=0;
for(int l=2,r=0;l<=n;l=r+1){
r=n/(n/l);
(res+=1ll*(n/l)*(n/l)%MOD*(varphi(r)-varphi(l-1)))%=MOD;
}
printf("%lld\n",(2ll*res+1ll*n*n)%MOD);
return 0;
}