先从一道简单题入手 (LCM sum)
求
令k=i/d
gcd里面同除d
我们发现枚举到n/d 与 d是等价的
这道题就可以转化为
杜教筛筛第一坨, 然后整除分块
#include<bits/stdc++.h>
#define N 1000050
#define LL long long
#define Mod 1000000007
#define inv2 500000004
#define inv6 166666668
using namespace std;
int prim[N], isp[N], tot, phi[N];
LL val[N],n;
map<LL,LL> F;
void prework(){
phi[1] = val[1] = 1;
for(int i=2;i<=N-50;i++){
if(!isp[i]) prim[++tot] = i, phi[i] = 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){
phi[i*prim[j]] = phi[i] * prim[j];
break;
}
phi[i*prim[j]] = phi[i] * (prim[j] - 1);
}
}
for(int i=2;i<=N-50;i++) val[i] = (LL)phi[i] * i % Mod * i % Mod;
for(int i=2;i<=N-50;i++) val[i] = (val[i] + val[i-1]) % Mod;
}
LL Sum(LL x){ x %= Mod; return x * (x+1) % Mod * inv2 % Mod;}
LL calc(LL x){ x %= Mod; return x * (x+1) % Mod * ((x*2+1) % Mod) % Mod * inv6 % Mod;}
LL getf(LL x){
if(x<=N-50) return val[x];
if(F[x]) return F[x];
LL ans = Sum(x); ans = (ans * ans) % Mod;
for(LL l=2,r;l<=x;l=r+1){
LL v = x/l; r = x/v;
ans -= (calc(r) - calc(l-1)) * getf(v) % Mod;
ans = (ans % Mod + Mod) % Mod;
} return F[x] = ans;
}
int main(){
prework(); scanf("%lld",&n); LL ans = 0;
for(LL l=1,r;l<=n;l=r+1){
LL v = n/l; r = n/v;
ans += Sum(v) * (getf(r) - getf(l-1)) % Mod;
ans = (ans % Mod + Mod) % Mod;
} printf("%lld",ans); return 0;
}