Address
https://www.lydsy.com/JudgeOnline/problem.php?id=2154
Solution
显然是莫比乌斯反演。
∑i=1N∑j=1Mlcm(i,j)
∑
i
=
1
N
∑
j
=
1
M
lcm
(
i
,
j
)
=∑i=1N∑j=1Mijgcd(i,j)
=
∑
i
=
1
N
∑
j
=
1
M
i
j
gcd
(
i
,
j
)
∑d∑i=1N∑j=1Mijd[gcd(i,j)=d]
∑
d
∑
i
=
1
N
∑
j
=
1
M
i
j
d
[
gcd
(
i
,
j
)
=
d
]
=∑d∑i=1⌊Nd⌋∑j=1⌊Md⌋dij[gcd(i,j)=1]
=
∑
d
∑
i
=
1
⌊
N
d
⌋
∑
j
=
1
⌊
M
d
⌋
d
i
j
[
gcd
(
i
,
j
)
=
1
]
=∑dd∑i=1⌊Nd⌋∑j=1⌊Md⌋ij∑k|gcd(i,j)μ(k)
=
∑
d
d
∑
i
=
1
⌊
N
d
⌋
∑
j
=
1
⌊
M
d
⌋
i
j
∑
k
|
gcd
(
i
,
j
)
μ
(
k
)
=∑dd∑k∑i=1,k|i⌊Nd⌋∑j=1,k|j⌊Md⌋ijμ(k)
=
∑
d
d
∑
k
∑
i
=
1
,
k
|
i
⌊
N
d
⌋
∑
j
=
1
,
k
|
j
⌊
M
d
⌋
i
j
μ
(
k
)
=∑dd∑kk2S(⌊Ndk⌋)S(⌊Mdk⌋)μ(k)
=
∑
d
d
∑
k
k
2
S
(
⌊
N
d
k
⌋
)
S
(
⌊
M
d
k
⌋
)
μ
(
k
)
其中 S(x)=x(x+1)2 S ( x ) = x ( x + 1 ) 2 。
发现下取整内的分母是乘积的形式,还是不好做。
所以设 T=dk T = d k :
∑T∑k|TTkk2S(⌊NT⌋)S(⌊MT⌋)μ(k)
∑
T
∑
k
|
T
T
k
k
2
S
(
⌊
N
T
⌋
)
S
(
⌊
M
T
⌋
)
μ
(
k
)
=∑TTS(⌊NT⌋)S(⌊MT⌋)∑k|Tkμ(k)
=
∑
T
T
S
(
⌊
N
T
⌋
)
S
(
⌊
M
T
⌋
)
∑
k
|
T
k
μ
(
k
)
再考虑求 f(T)=∑k|Tkμ(k) f ( T ) = ∑ k | T k μ ( k ) 。
对于任意的 gcd(S,T)=1 gcd ( S , T ) = 1 ,都有:
f(ST)=∑k|STkμ(k)
f
(
S
T
)
=
∑
k
|
S
T
k
μ
(
k
)
∑d|S∑k|Tdkμ(dk)
∑
d
|
S
∑
k
|
T
d
k
μ
(
d
k
)
=(∑d|Sμ(d))(∑k|Tμ(k))
=
(
∑
d
|
S
μ
(
d
)
)
(
∑
k
|
T
μ
(
k
)
)
=f(S)f(T)
=
f
(
S
)
f
(
T
)
我们得到: f f 是积性函数。可以线性筛求。
∀n为质数且k≥1,f(nk)=1−n
∀
n
为
质
数
且
k
≥
1
,
f
(
n
k
)
=
1
−
n
∀m为质数且m|n,f(nm)=f(n)
∀
m
为
质
数
且
m
|
n
,
f
(
n
m
)
=
f
(
n
)
∀gcd(n,m)=1,f(nm)=f(n)f(m)
∀
gcd
(
n
,
m
)
=
1
,
f
(
n
m
)
=
f
(
n
)
f
(
m
)
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Step(i, a, b, x) for (i = a; i <= b; i += x)
using namespace std;
const int MaxN = 1e7, N = 1e7 + 5, ZZQ = 20101009;
int n, m, tot, pri[N], zzq[N], ans;
bool mark[N];
void sieve() {
int i, j;
mark[0] = mark[zzq[1] = 1] = 1;
For (i, 2, MaxN) {
if (!mark[i]) zzq[pri[++tot] = i] = 1 - i + ZZQ;
For (j, 1, tot) {
if (1ll * i * pri[j] > MaxN) break;
mark[i * pri[j]] = 1;
if (i % pri[j] == 0) {
zzq[i * pri[j]] = zzq[i];
break;
}
else zzq[i * pri[j]] = 1ll * zzq[i] * zzq[pri[j]] % ZZQ;
}
}
}
int S(int n) {
return (1ll * n * (n + 1) >> 1) % ZZQ;
}
int main() {
int i;
cin >> n >> m;
sieve();
For (i, 1, min(n, m))
ans = (ans + 1ll * i * S(n / i) % ZZQ * S(m / i)
% ZZQ * zzq[i] % ZZQ) % ZZQ;
cout << ans << endl;
return 0;
}