题目就是求 ∑ni=1∑nj=1i+jgcd(i,j)−2n2 ∑ i = 1 n ∑ j = 1 n i + j gcd ( i , j ) − 2 n 2
枚举 d=gcd(i,j) d = gcd ( i , j ) ,
代码:
#include
#include
#include
#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];
void add(int x,int y)
{
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);
H.add(n,re);
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;
}