题目
分析
d
(
x
y
)
=
∑
d
1
∣
x
∑
d
2
∣
y
[
gcd
(
d
1
,
d
2
)
=
1
]
d(xy)=\sum_{d_1|x}\sum_{d_2|y}[\gcd(d_1,d_2) = 1]
d(xy)=d1∣x∑d2∣y∑[gcd(d1,d2)=1] 我们证明每个因子与
gcd
(
d
1
,
d
2
)
=
1
\gcd(d_1,d_2) = 1
gcd(d1,d2)=1 的双射关系:
设
x
=
∏
i
=
1
n
p
i
a
i
,
y
=
∏
i
=
1
n
p
i
b
i
(
a
i
+
b
i
≠
0
)
x = \prod_{i = 1}^{n}{p_i}^{a_i}, y = \prod_{i = 1}^{n}{p_i}^{b_i}\ (a_i + b_i \neq 0)
x=∏i=1npiai,y=∏i=1npibi (ai+bi=0)。
考虑
x
y
xy
xy 的一个因子
k
=
∏
i
=
1
n
p
i
t
i
k = \prod_{i = 1}^{n}{p_i}^{t_i}
k=∏i=1npiti,如果
t
i
≤
a
i
t_i \leq a_i
ti≤ai,将
q
t
i
q^{t_i}
qti 乘入
d
1
d_1
d1,否则将
q
t
i
−
a
i
q^{t_i - a_i}
qti−ai 乘入
d
2
d_2
d2,这样一来显然
gcd
(
d
1
,
d
2
)
=
1
\gcd(d_1,d_2) = 1
gcd(d1,d2)=1,也就建立了
k
k
k 到
gcd
(
d
1
,
d
2
)
=
1
\gcd(d_1,d_2) = 1
gcd(d1,d2)=1 的单射。再考虑由
gcd
(
d
1
,
d
2
)
=
1
\gcd(d_1,d_2) = 1
gcd(d1,d2)=1 映射回
k
k
k,也很简单,看每个
p
i
p_i
pi 在
d
1
d_1
d1 里面还是在
d
2
d_2
d2 里面即可,这也是一个单射。
由此我们证明出了每个因子与每个
gcd
(
d
1
,
d
2
)
=
1
\gcd(d_1,d_2) = 1
gcd(d1,d2)=1 之间是一一映射的,原式得证。
接下来就是反演了,不妨设 n ≥ m n \geq m n≥m: ∑ i = 1 n ∑ j = 1 m d ( i j ) = ∑ i = 1 n ∑ j = 1 m ∑ d 1 ∣ i ∑ d 2 ∣ j [ gcd ( d 1 , d 2 ) = 1 ] = ∑ d 1 = 1 n ∑ d 2 = 1 m ⌊ n d 1 ⌋ ⌊ m d 2 ⌋ [ gcd ( d 1 , d 2 ) = 1 ] = ∑ d = 1 m μ ( d ) ∑ d 1 = 1 n ∑ d 2 = 1 m [ d ∣ d 1 ] [ d ∣ d 2 ] ⌊ n d 1 ⌋ ⌊ m d 2 ⌋ = ∑ d = 1 m μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ n d ⋅ i ⌋ ⌊ m d ⋅ j ⌋ = ∑ d = 1 m μ ( d ) ( ∑ i = 1 ⌊ n d ⌋ ⌊ ⌊ n d ⌋ i ⌋ ) ( ∑ j = 1 ⌊ m d ⌋ ⌊ ⌊ m d ⌋ j ⌋ ) \begin{aligned}&\sum_{i = 1}^n\sum_{j = 1}^m d(ij) \\=&\sum_{i = 1}^n\sum_{j = 1}^m\sum_{d_1|i}\sum_{d_2|j}[\gcd(d_1,d_2) = 1] \\=&\sum_{d_1 = 1}^n\sum_{d_2 = 1}^m\left\lfloor\frac{n}{d_1}\right\rfloor\left\lfloor\frac{m}{d_2}\right\rfloor[\gcd(d_1,d_2) = 1] \\=&\sum_{d = 1}^m\mu(d)\sum_{d_1 = 1}^n\sum_{d_2 = 1}^m[d|d_1][d|d_2]\left\lfloor\frac{n}{d_1}\right\rfloor\left\lfloor\frac{m}{d_2}\right\rfloor\\=&\sum_{d = 1}^m\mu(d)\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor}\left\lfloor\frac{n}{d\cdot i}\right\rfloor\left\lfloor\frac{m}{d\cdot j}\right\rfloor\\=&\sum_{d = 1}^m\mu(d)\left(\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\left\lfloor\frac{\left\lfloor\frac{n}{d}\right\rfloor}{i}\right\rfloor\right)\left(\sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor}\left\lfloor\frac{\left\lfloor\frac{m}{d}\right\rfloor}{j}\right\rfloor\right)\end{aligned} =====i=1∑nj=1∑md(ij)i=1∑nj=1∑md1∣i∑d2∣j∑[gcd(d1,d2)=1]d1=1∑nd2=1∑m⌊d1n⌋⌊d2m⌋[gcd(d1,d2)=1]d=1∑mμ(d)d1=1∑nd2=1∑m[d∣d1][d∣d2]⌊d1n⌋⌊d2m⌋d=1∑mμ(d)i=1∑⌊dn⌋j=1∑⌊dm⌋⌊d⋅in⌋⌊d⋅jm⌋d=1∑mμ(d)⎝⎜⎛i=1∑⌊dn⌋⌊i⌊dn⌋⌋⎠⎟⎞⎝⎜⎛j=1∑⌊dm⌋⌊j⌊dm⌋⌋⎠⎟⎞ 令 f ( x ) = ∑ i = 1 x ⌊ x i ⌋ f(x) = \sum\limits_{i = 1}^{x}\left\lfloor\frac{x}{i}\right\rfloor f(x)=i=1∑x⌊ix⌋,它可以 O ( n n ) O(n\sqrt n) O(nn) 初始化,那么原式也可以 O ( n ) O(\sqrt n) O(n) 求了。
代码
#include <bits/stdc++.h>
typedef long long LL;
const int MAXN = 50000;
LL Num[MAXN + 5];
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() && (LL)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] + Mu[i];
}
for (int i = 1; i <= n; i++) {
for (int lft = 1, rgt = 1; lft <= i; lft = rgt + 1) {
rgt = i / (i / lft);
Num[i] += (LL)(rgt - lft + 1) * (i / lft);
}
}
}
int main() {
Init(MAXN);
int T; scanf("%d", &T);
while (T--) {
int N, M; scanf("%d%d", &N, &M);
if (N < M) std::swap(N, M);
LL Ans = 0;
for (int lft = 1, rgt = 1; lft <= M; lft = rgt + 1) {
rgt = std::min(M / (M / lft), N / (N / lft));
Ans += (LL)(Mu[rgt] - Mu[lft - 1]) * Num[N / lft] * Num[M / lft];
}
printf("%lld\n", Ans);
}
return 0;
}