知识点:
Dirichlet 前缀和 + 线性筛。
推导:
默认 (n leq m)
(ans = displaystyle sum_{i = 1}^n sum_{j = 1}^{m} lcm(i,j) \ = displaystyle sum_{d = 1}^{n} d sum_{i = 1}^{lfloor frac{n}{d} floor} sum_{j = 1}^{lfloor frac{m}{d} floor} ij \ = displaystyle sum_{d = 1}^{n} d sum_{i = 1}^{lfloor frac{n}{d} floor} sum_{j = 1}^{lfloor frac{m}{d} floor} ij \ = displaystyle sum_{d = 1}^{n} d sum_{k = 1}^{lfloor frac{n}{d} floor} mu(k)k^2 sum_{i = 1}^{lfloor frac{n}{kd} floor} sum_{j = 1}^{lfloor frac{m}{kd} floor} ij)
下面不妨令 (T = kd)。可以得到:
(ans = displaystyle sum_{T = 1}^n T sum_{d|T} mu(d)d sum_{i = 1}^{lfloor frac{n}{T} floor} sum_{j = 1}^{lfloor frac{m}{T} floor} ij)
不妨令 (g(n, T)) = (displaystyle sum_{i = 1}^{lfloor frac{n}{T} floor}),可以很容易得到 (g(T) = (frac{n}{T} + 1) * frac{n}{T} / 2)
那么
(ans = displaystyle sum_{T = 1}^n (T sum_{d|T} mu(d)d) imes g(n, T) imes g(m, T))
前面的 (displaystyle sum_{d|T} mu(d)d) 用 Dirichlet 前缀和预处理即可在 (O(n log log n)) 的复杂度内完成问题的预处理。
对于询问用整除分块优化即可做到 (sqrt{n}) 处理。
Code
#include <bits/stdc++.h>
using namespace std;
const int Mod = 20101009, MAXN = 1e7 + 5, inv = (Mod + 1) >> 1;
int n, m;
int Prime[MAXN / 11], Mu[MAXN], tot = 0, S[MAXN];
bool bk[MAXN];
void GetPrime(int N) {
Mu[1] = 1;
for(int i = 2 ; i <= N ; i ++) {
if(!bk[i]) Prime[++ tot] = i, Mu[i] = -1;
for(int j = 1 ; j <= tot && Prime[j] * i <= N; j ++) {
bk[Prime[j] * i] = 1;
if(i % Prime[j] == 0) break;
Mu[Prime[j] * i] = - Mu[i];
}
}
for(int i = 1 ; i <= N ; i ++) S[i] = 1ll * ((Mu[i] + Mod) % Mod) * i % Mod;
return ;
}
int Sum(int x) { return 1ll * x * (x + 1) % Mod * inv % Mod; }
int main() {
cin >> n >> m;
if(n > m) swap(n, m);
GetPrime(n);
for(int i = 1 ; i <= tot ; i ++)
for(int j = 1 ; j * Prime[i] <= n ; j ++)
S[Prime[i] * j] += S[j], S[Prime[i] * j] %= Mod;
int Ans = 0;
for(int i = 1 ; i <= n ; i ++) {
Ans += 1ll * i * S[i] % Mod * Sum(n / i) % Mod * Sum(m / i) % Mod;
Ans %= Mod;
}
cout << Ans;
return 0;
}