题目大意:
分析:
d
(
i
j
)
=
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
j
/
y
)
=
1
]
d(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,j/y)=1]
d(ij)=∑x∣i∑y∣j[gcd(x,j/y)=1]
a
n
s
=
∑
i
=
1
n
∑
j
=
1
m
d
(
i
j
)
ans=\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)
ans=∑i=1n∑j=1md(ij)
=
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
j
/
y
)
=
1
]
=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{x|i}\sum_{y|j}[gcd(x,j/y)=1]
=∑i=1n∑j=1m∑x∣i∑y∣j[gcd(x,j/y)=1]
=
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
∑
d
∣
g
c
d
(
x
,
j
/
y
)
μ
(
d
)
=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{x|i}\sum_{y|j}\sum_{d|gcd(x,j/y)}μ(d)
=∑i=1n∑j=1m∑x∣i∑y∣j∑d∣gcd(x,j/y)μ(d)
=
∑
i
=
1
n
∑
j
=
1
m
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
∑
d
∣
x
,
x
∣
i
∑
d
∣
(
j
/
y
)
,
y
∣
j
=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d|gcd(i,j)}μ(d)\sum_{d|x,x|i}\sum_{d|(j/y),y|j}
=∑i=1n∑j=1m∑d∣gcd(i,j)μ(d)∑d∣x,x∣i∑d∣(j/y),y∣j
设
x
=
x
1
∗
d
x=x1*d
x=x1∗d,
i
=
s
∗
d
i=s*d
i=s∗d,因为
x
∣
i
x|i
x∣i所以
x
1
∣
s
x1|s
x1∣s,因此
x
1
∣
(
i
/
d
)
x1|(i/d)
x1∣(i/d)
=
∑
i
=
1
n
∑
j
=
1
m
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
∑
x
1
∣
(
i
/
d
)
∑
y
∣
(
j
/
d
)
=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d|gcd(i,j)}μ(d)\sum_{x1|(i/d)}\sum_{y|(j/d)}
=∑i=1n∑j=1m∑d∣gcd(i,j)μ(d)∑x1∣(i/d)∑y∣(j/d)
设
d
(
i
)
d(i)
d(i)表示
i
i
i的约数个数,
=
∑
i
=
1
n
∑
j
=
1
m
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
d
(
i
/
d
)
d
(
j
/
d
)
=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d|gcd(i,j)}μ(d)d(i/d)d(j/d)
=∑i=1n∑j=1m∑d∣gcd(i,j)μ(d)d(i/d)d(j/d)
=
∑
d
∣
n
μ
(
d
)
∑
i
=
1
n
/
d
d
(
i
)
∑
j
=
1
m
/
d
d
(
j
)
=\sum_{d|n}μ(d)\sum_{i=1}^{n/d}d(i)\sum_{j=1}^{m/d}d(j)
=∑d∣nμ(d)∑i=1n/dd(i)∑j=1m/dd(j)
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)处理出d()
对
μ
(
d
)
μ(d)
μ(d)和
d
(
i
)
d(i)
d(i)做前缀和,
然后每个询问整除分块即可
时间复杂度:O(nlogn+T
n
\sqrt n
n)
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define N 50005
using namespace std;
typedef long long ll;
int sum1[N], sum2[N], pri[N], mu[N], C[N], n, m, T, cnt;
bool vis[N];
ll ans;
void Pre_Work() {
mu[1] = 1;
rep(i, 2, N - 5) {
if (!vis[i]) { pri[++cnt] = i; mu[i] = -1; }
rep(j, 1, cnt) {
if ((ll)pri[j] * i > N - 5) break;
vis[pri[j] * i] = 1;
if (i % pri[j] == 0) { mu[pri[j] * i] = 0; break; } else mu[pri[j] * i] = - mu[i];
}
}
rep(i, 1, N - 5) sum1[i] = sum1[i - 1] + mu[i];
rep(i, 1, N - 5)
rep(j, 1, (N - 5) / i) C[i * j]++;
rep(i, 1, N - 5) sum2[i] = sum2[i - 1] + C[i];
}
int main() {
Pre_Work();
scanf("%d", &T);
rep(i, 1, T) {
scanf("%d %d", &n, &m);
if (n > m) swap(n, m);
int L = 1, R = 0;
ans = 0;
while (L <= n) {
R = min(n / (n / L), m / (m / L));
ans = ans + 1ll * (sum1[R] - sum1[L - 1]) * sum2[n / L] * sum2[m / L];
L = R + 1;
}
printf("%lld\n", ans);
}
return 0;
}