# [联合集训6-26] 盒子 莫比乌斯反演+杜教筛

$\sum _{d=1}^{n}\sum _{i=1}^{n}\sum _{j=1}^{n}\left[gcd\left(i,j\right)=d\right]\frac{i+j}{d}$

$\sum _{k=1}^{n}\mu \left(k\right)\sum _{d=1}^{⌊\frac{n}{k}⌋}\sum _{i=1}^{⌊\frac{n}{kd}⌋}\sum _{i=1}^{⌊\frac{n}{kd}⌋}\frac{ikd+jkd}{d}=\sum _{k=1}^{n}\mu \left(k\right)\cdot k\sum _{d=1}^{⌊\frac{n}{k}⌋}⌊\frac{n}{kd}{⌋}^{2}\left(⌊\frac{n}{kd}⌋+1\right)$

$f\left(n\right)=\sum _{i=1}^{n}\mu \left(k\right)\cdot k,g\left(n\right)=\sum _{i=1}^{n}⌊\frac{n}{i}{⌋}^{2}\left(⌊\frac{n}{i}⌋+1\right)$$f(n)=\sum_{i=1}^n\mu(k)\cdot k,g(n)=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor^2(\lfloor\frac{n}{i}\rfloor+1)$。我们只要能筛$f,g$$f,g$的就能分块求了。$g$$g$显然能直接分块$O\left(\sqrt{n}\right)$$O(\sqrt n)$求，$f$$f$可以卷上$id$$id$函数之后用杜教筛求，具体地：
$f\left(n\right)=\sum _{i=1}^{n}\sum _{d|i}\mu \left(d\right)\cdot d\cdot \frac{i}{d}-\sum _{i=2}^{n}\sum _{d|i,d

$f\left(n\right)=1-\sum _{i=2}^{n}i\cdot f\left(⌊\frac{n}{i}⌋\right)$

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define up(x,y) (x=(x+(y))%mod)
using namespace std;
const int mod=1000000007,R=10000000;
int n,mk[R+5],pri[670000],num;
bool flag[R+5];
ll ans;
struct ha
{
int cnt,con[R+5],a[R+5],b[R+5],nxt[R+5];
{
int id=x%R;
a[++cnt]=x;b[cnt]=y;
nxt[cnt]=con[id];
con[id]=cnt;
}
int qry(int x)
{
int id=x%R;
for(int p=con[id];p;p=nxt[p])
if(a[p]==x) return b[p];
return -1;
}
}H;
void getpri(int n)
{
memset(flag,1,sizeof(flag));
flag[1]=0;mk[1]=1;
for(int i=2;i<=n;i++)
{
if(flag[i]) {pri[++num]=i;mk[i]=-i;}
for(int j=1;j<=num&&i*pri[j]<=n;j++)
{
flag[i*pri[j]]=0;
if(i%pri[j]==0) {mk[i*pri[j]]=0;break;}
mk[i*pri[j]]=-mk[i]*pri[j];
}
}
for(int i=2;i<=n;i++)
up(mk[i],mk[i-1]);
}
ll djs(int n)
{
if(n<=R) return mk[n];
int hh=H.qry(n);
if(hh!=-1) return hh;
ll re=1;
for(int l=2,r,x;l<=n;l=r+1)
x=n/l,r=n/x,up(re,-djs(x)*((ll)(l+r)*(r-l+1)/2)%mod);
return re;
}
ll calc(int n)
{
ll re=0;
for(int l=1,r,x;l<=n;l=r+1)
x=n/l,r=n/x,up(re,(ll)x*x%mod*(x+1)%mod*(r-l+1));
return re;
}
ll solve(int n)
{
ll re=0;
for(int l=1,r,x;l<=n;l=r+1)
x=n/l,r=n/x,up(re,(djs(r)-djs(l-1))*calc(x));
return re;
}
int main()
{
freopen("box.in","r",stdin);
freopen("box.out","w",stdout);
scanf("%d",&n);
getpri(R);
printf("%lld",((solve(n)-2ll*n*n)%mod+mod)%mod);
return 0;
}