传送门
记住这个性质
那么原式就是
考虑求
然后整除分块一波, 求
的前缀和就可以了, 杜教筛解决
#include<bits/stdc++.h>
#define N 5000050
#define LL long long
#define Mod 1000000007
using namespace std;
int prim[N], tot, isp[N], mu[N];
LL val[N];
map<int,LL> F;
void prework(){
mu[1] = val[1] = 1;
for(int i=2;i<=N-50;i++){
if(!isp[i]) prim[++tot] = i, mu[i] = -1;
for(int j=1;j<=tot;j++){
if(i * prim[j] > N - 50) break;
isp[i * prim[j]] = 1;
if(i % prim[j] == 0) break;
mu[i * prim[j]] = -mu[i];
}
}
for(int i=1;i<=N-50;i++) val[i] = mu[i] * i;
for(int i=2;i<=N-50;i++) val[i] = (val[i] + val[i-1]) % Mod;
}
LL getf(int x){
if(x <= N-50) return val[x];
if(F[x]) return F[x];
LL ans = 1;
for(int l=2,r;l<=x;l=r+1){
int v = x/l; r = x/v;
ans -= (LL)(l+r) * (LL)(r-l+1) / 2 * getf(v);
ans = (ans % Mod + Mod) % Mod;
}
return F[x] = ans;
}
int main(){
prework();
int n; scanf("%d",&n);
LL ans = 0;
for(int l=1,r;l<=n;l=r+1){
int v = n/l; r = n/v;
ans += (LL)v * (getf(r) - getf(l-1)) % Mod;
ans = (ans % Mod + Mod) % Mod;
} ans = (ans * ans) % Mod;
printf("%lld",ans); return 0;
}