题目
分析
不妨设
n
≥
m
n \geq m
n≥m:
∑
i
=
1
n
∑
j
=
1
m
lcm
(
i
,
j
)
=
∑
i
=
1
n
∑
j
=
1
m
i
j
gcd
(
i
,
j
)
=
∑
d
=
1
m
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
i
j
d
[
gcd
(
i
,
j
)
=
1
]
=
∑
d
=
1
m
1
d
∑
k
=
1
⌊
m
d
⌋
μ
(
k
)
∑
i
=
1
⌊
n
d
k
⌋
∑
j
=
1
⌊
m
d
k
⌋
(
i
d
k
)
(
j
d
k
)
=
∑
d
=
1
m
d
∑
k
=
1
⌊
m
d
⌋
μ
(
k
)
k
2
∑
i
=
1
⌊
n
d
k
⌋
∑
j
=
1
⌊
m
d
k
⌋
i
j
\begin{aligned} &\sum_{i = 1}^{n}\sum_{j = 1}^m \text{lcm}(i, j) \\ =&\sum_{i = 1}^{n}\sum_{j = 1}^m \frac{ij}{\gcd(i, j)} \\=&\sum_{d = 1}^{m} \sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor}\frac{ij}{d}[\gcd(i, j) = 1] \\ =&\sum_{d = 1}^{m}\frac{1}{d}\sum_{k = 1}^{\left\lfloor\frac{m}{d}\right\rfloor}\mu(k)\sum_{i = 1}^{\left\lfloor\frac{n}{dk}\right\rfloor}\sum_{j = 1}^{\left\lfloor\frac{m}{dk}\right\rfloor}(idk)(jdk) \\=&\sum_{d = 1}^{m}d\sum_{k = 1}^{\left\lfloor\frac{m}{d}\right\rfloor}\mu(k)k^2\sum_{i = 1}^{\left\lfloor\frac{n}{dk}\right\rfloor}\sum_{j = 1}^{\left\lfloor\frac{m}{dk}\right\rfloor}ij\end{aligned}
====i=1∑nj=1∑mlcm(i,j)i=1∑nj=1∑mgcd(i,j)ijd=1∑mi=1∑⌊dn⌋j=1∑⌊dm⌋dij[gcd(i,j)=1]d=1∑md1k=1∑⌊dm⌋μ(k)i=1∑⌊dkn⌋j=1∑⌊dkm⌋(idk)(jdk)d=1∑mdk=1∑⌊dm⌋μ(k)k2i=1∑⌊dkn⌋j=1∑⌊dkm⌋ij 令
f
(
n
,
m
)
=
∑
k
=
1
m
μ
(
k
)
k
2
∑
i
=
1
⌊
n
k
⌋
∑
j
=
1
⌊
m
k
⌋
i
j
f(n, m) = \sum\limits_{k = 1}^{m}\mu(k)k^2\sum\limits_{i = 1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum\limits_{j = 1}^{\left\lfloor\frac{m}{k}\right\rfloor}ij
f(n,m)=k=1∑mμ(k)k2i=1∑⌊kn⌋j=1∑⌊km⌋ij,由于
∑
i
=
1
⌊
n
k
⌋
∑
j
=
1
⌊
m
k
⌋
i
j
=
(
∑
i
=
1
⌊
n
k
⌋
i
)
(
∑
j
=
1
⌊
m
k
⌋
j
)
\sum\limits_{i = 1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum\limits_{j = 1}^{\left\lfloor\frac{m}{k}\right\rfloor}ij =\left( \sum\limits_{i = 1}^{\left\lfloor\frac{n}{k}\right\rfloor}i\right)\left(\sum\limits_{j = 1}^{\left\lfloor\frac{m}{k}\right\rfloor}j\right)
i=1∑⌊kn⌋j=1∑⌊km⌋ij=⎝⎛i=1∑⌊kn⌋i⎠⎞⎝⎛j=1∑⌊km⌋j⎠⎞ 即两个等差数列之和的乘积,所以这个可以数论分块求出。原式即为
∑
d
=
1
m
d
f
(
⌊
n
d
⌋
,
⌊
m
d
⌋
)
\sum_{d = 1}^{m}df\left(\left\lfloor\frac{n}{d}\right\rfloor, \left\lfloor\frac{m}{d}\right\rfloor\right)
d=1∑mdf(⌊dn⌋,⌊dm⌋) 亦可数论分块。总时间复杂度
O
(
n
)
O(n)
O(n)。
代码
#include <bits/stdc++.h>
typedef long long LL;
const int MAXN = 10000000;
const int MOD = 20101009;
int Mu[MAXN + 5];
bool Vis[MAXN + 5];
std::vector<int> Primes;
void Init(int n) {
Mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!Vis[i])
Mu[i] = -1, Primes.push_back(i);
for (int j = 0; j < (int)Primes.size() && i * Primes[j] <= n; j++) {
Vis[i * Primes[j]] = true;
if (i % Primes[j] == 0) {
Mu[i * Primes[j]] = 0;
break;
}
Mu[i * Primes[j]] = -Mu[i];
}
Mu[i] = ((Mu[i - 1] + (LL)Mu[i] * i * i % MOD) % MOD + MOD) % MOD;
}
}
int Sum(int n) {
return (LL)n * (n + 1) / 2 % MOD;
}
int Calc(int n, int m) {
if (n < m) std::swap(n, m);
int ret = 0;
for (int lft = 1, rgt = 1; lft <= m; lft = rgt + 1) {
rgt = std::min(n / (n / lft), m / (m / lft));
ret = (ret + (LL)(Mu[rgt] - Mu[lft - 1]) % MOD * Sum(n / lft) % MOD * Sum(m / lft) % MOD) % MOD;
}
return (ret + MOD) % MOD;
}
int main() {
Init(MAXN);
int N, M; scanf("%d%d", &N, &M);
if (N < M) std::swap(N, M);
int Ans = 0;
for (int lft = 1, rgt = 1; lft <= M; lft = rgt + 1) {
rgt = std::min(M / (M / lft), N / (N / lft));
Ans = (Ans + (LL)(lft + rgt) * (rgt - lft + 1) / 2 % MOD * Calc(N / lft, M / lft)) % MOD;
}
printf("%d", Ans);
return 0;
}