n
,
m
≤
1
e
7
n,m\leq1e7
n,m≤1e7,求
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
\sum\limits_{i=1}^n\sum\limits_{j=1}^{m}lcm(i,j)
i=1∑nj=1∑mlcm(i,j)
不妨设
n
≤
m
n\leq m
n≤m,则原式
=
∑
i
=
1
n
∑
j
=
1
m
i
∗
j
g
c
d
(
i
,
j
)
=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\frac{i*j}{gcd(i,j)}
=i=1∑nj=1∑mgcd(i,j)i∗j
=
∑
g
=
1
n
1
g
∑
i
=
1
n
∑
j
=
1
m
i
j
[
g
c
d
(
i
,
j
)
=
g
]
=\sum\limits_{g=1}^{n}\frac{1}{g}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}ij[gcd(i,j)=g]
=g=1∑ng1i=1∑nj=1∑mij[gcd(i,j)=g]
=
∑
g
=
1
n
g
∑
i
=
1
n
/
g
∑
j
=
1
m
/
g
i
j
[
g
c
d
(
i
,
j
)
=
1
]
=\sum\limits_{g=1}^{n}g\sum\limits_{i=1}^{n/g}\sum\limits_{j=1}^{m/g}ij[gcd(i,j)=1]
=g=1∑ngi=1∑n/gj=1∑m/gij[gcd(i,j)=1]
=
∑
g
=
1
n
g
∑
i
=
1
n
/
g
∑
j
=
1
m
/
g
i
j
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
=\sum\limits_{g=1}^{n}g\sum\limits_{i=1}^{n/g}\sum\limits_{j=1}^{m/g}ij\sum\limits_{d|gcd(i,j)}\mu(d)
=g=1∑ngi=1∑n/gj=1∑m/gijd∣gcd(i,j)∑μ(d)
=
∑
g
=
1
n
g
∑
d
=
1
n
/
g
μ
(
d
)
∑
i
=
1
n
/
g
d
∑
j
=
1
m
/
g
d
i
j
d
2
=\sum\limits_{g=1}^{n}g\sum\limits_{d=1}^{n/g}\mu(d)\sum\limits_{i=1}^{n/gd}\sum\limits_{j=1}^{m/gd}ijd^2
=g=1∑ngd=1∑n/gμ(d)i=1∑n/gdj=1∑m/gdijd2
=
∑
g
=
1
n
g
∑
d
=
1
n
/
g
μ
(
d
)
d
2
n
g
d
∗
(
n
g
d
+
1
)
2
∗
m
g
d
∗
(
m
g
d
+
1
)
2
=\sum\limits_{g=1}^{n}g\sum\limits_{d=1}^{n/g}\mu(d)d^2\frac{\frac{n}{gd}*(\frac{n}{gd}+1)}{2}*\frac{\frac{m}{gd}*(\frac{m}{gd}+1)}{2}
=g=1∑ngd=1∑n/gμ(d)d22gdn∗(gdn+1)∗2gdm∗(gdm+1)
μ
(
d
)
d
2
\mu(d)d^2
μ(d)d2可以线性时间预处理前缀和,两个分式
O
(
1
)
O(1)
O(1)计算得到,对于内外两层各做一次分块。时间复杂度为
O
(
n
∗
n
)
=
O
(
n
)
O(\sqrt n *\sqrt n)=O(n)
O(n∗n)=O(n)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=1e7+7;
int pri[N],tot=0;
bool ok[N];
int mu[N];
ll sum[N];
ll n,m;
const int mod=20101009;
void getmu() {
mu[1]=1;
for(int i=2;i<=n;i++) {
if(!ok[i]) pri[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*pri[j]<=n;j++) {
ok[i*pri[j]]=1;
if(i%pri[j]) mu[i*pri[j]]=-mu[i];
else { mu[i*pri[j]]=0;break; }
}
}
sum[1]=mu[1];
for(int i=2;i<=n;i++) {
sum[i]=sum[i-1]+((1LL*i*i)%mod*mu[i])%mod;
sum[i]%=mod;
}
}
ll cal(ll x) { return (x*(x+1)>>1)%mod; }
ll sub(ll x,ll y) {
if(x-y>=0) return x-y;
else return x-y+mod;
}
ll solve(ll n,ll m) {
ll ans=0;
for(int l=1,r=0;l<=n;l=r+1) {
r=min(n/(n/l),m/(m/l));
ans+=sub(sum[r],sum[l-1])*cal(n/l)%mod*cal(m/l)%mod;
ans%=mod;
}
return ans;
}
int main() {
scanf("%lld%lld",&n,&m);
if(n>m) swap(n,m);
getmu();
ll ans=0;
for(int l=1,r=0;l<=n;l=r+1) {
r=min(n/(n/l),m/(m/l));
ans+=(1LL*(l+r)*(r-l+1)/2)%mod*solve(n/l,m/l)%mod;
ans%=mod;
}
printf("%lld\n",ans);
return 0;
}