不妨设
n≤m
。
==∑i=1n∑j=1mlcm(i,j)gcd(i,j)∑d=1n∑i=1⌊nd⌋∑j=1⌊md⌋(ijd)de(gcd(i,j))∑d=1ndd∑x=1⌊nd⌋μ(x)x2d∑i=1⌊ndx⌋∑j=1⌊mdx⌋idjd
在枚举 d 的同时顺便维护
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=500010,p=1000000007;
int mu[maxn],prm[maxn],vis[maxn],pw[maxn],sum[maxn],
n,m,tot;
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;
return x<0?x+p:x;
}
int pow(int b,int k)
{
int ret=1;
for (;k;k>>=1,b=(LL)b*b%p)
if (k&1) ret=(LL)ret*b%p;
return ret;
}
int main()
{
int ans=0,tem;
scanf("%d%d",&n,&m);
//m=n=500000;
if (n>m) swap(n,m);
mu[1]=1;
for (int i=2;i<=n;i++)
{
if (!vis[i])
{
mu[i]=p-1;
prm[++tot]=i;
}
for (int j=1;j<=tot&&(LL)i*prm[j]<=maxn;j++)
{
vis[i*prm[j]]=1;
if (i%prm[j]) mu[i*prm[j]]=dec(0,mu[i]);
else
{
mu[i*prm[j]]=0;
break;
}
}
}
for (int i=1;i<=m;i++) pw[i]=1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m/i;j++)
{
pw[j]=(LL)pw[j]*j%p;
sum[j]=inc(sum[j-1],pw[j]);
}
tem=0;
for (int j=1;j<=n/i;j++)
tem=inc(tem,(LL)mu[j]*pw[j]%p*pw[j]%p*sum[n/i/j]%p*sum[m/i/j]%p);
ans=inc(ans,(LL)pow(i,i)*tem%p);
}
printf("%d\n",ans);
}