P2257 YY的GCD 题解
萌萌柿子题。
定义 \(\mathbb{P}\) 为适当大小的质数集,\(P(x) = [x \in \mathbb{P}]\)。
\[\begin{align*}
&~~~~~\sum_{x = 1} ^ {N} \sum _ {y = 1} ^ {M}\left [ \gcd(x, y) \in \mathbb{P} \right]\\
&= \sum_{p = 1, p \in \mathbb{P}}\sum_{x = 1} ^ {N} \sum _ {y = 1} ^ {M} [\gcd(x, y) = p]\\
&= \sum_{p = 1, p \in \mathbb{P}}\sum_{x = 1} ^ {\left\lfloor \frac{N}{p} \right\rfloor} \sum _ {y = 1} ^ {\left\lfloor \frac{M}{p} \right\rfloor} [\gcd(x, y) = 1]\\
\end{align*}
\]
发现后面那一坨可以转换成 \(\mu\) 函数的格式。
\[\begin{align*}
&= \sum_{p = 1, p \in \mathbb{P}}\sum_{x = 1} ^ {\left\lfloor \frac{N}{p} \right\rfloor} \sum _ {y = 1} ^ {\left\lfloor \frac{M}{p} \right\rfloor} \sum_{d | \gcd(x, y)}\mu(d) \\
&= \sum_{p = 1, p \in \mathbb{P}} \sum_{d = 1} ^ {\left\lfloor \frac{\max(N, M)}{p} \right\rfloor}\mu(d) \sum_{x = 1} ^ {\left\lfloor \frac{N}{dp} \right\rfloor} \sum _ {y = 1} ^ {\left\lfloor \frac{M}{dp} \right\rfloor} 1 \\
&= \sum_{p = 1, p \in \mathbb{P}} \sum_{d = 1} ^ {\left\lfloor \frac{\max(N, M)}{p} \right\rfloor}\mu(d) \left\lfloor \frac{N}{dp} \right\rfloor \left\lfloor \frac{M}{dp} \right\rfloor \\
&= \sum _ {d = 1} ^ {\max(N, M)} \left \lfloor \frac{N}{d} \right \rfloor\left \lfloor \frac{M}{d} \right \rfloor \sum _ {p \mid d, p \in \mathbb{P}} \mu\left(\frac{d}{p}\right)\\
&= \sum _ {d = 1} ^ {\max(N, M)} \left \lfloor \frac{N}{d} \right \rfloor\left \lfloor \frac{M}{d} \right \rfloor \sum _ {p \mid d} P(p) \times \mu\left(\frac{d}{p}\right)\\
&= \sum _ {d = 1} ^ {\max(N, M)} \left \lfloor \frac{N}{d} \right \rfloor\left \lfloor \frac{M}{d} \right \rfloor \left(P \times \mu\right)(d)
\end{align*}
\]
后面那一坨就是狄利克雷卷积,然而我不会就自己想了一个做法。
对于每一个 \(d\) 预处理 \((P \times \mu)(d)\) 的值。
整除分块一下,此时同一个块里面 \(\left \lfloor \frac{N}{d} \right \rfloor\left \lfloor \frac{M}{d} \right \rfloor\) 是相同的,所以可以把该式提出来,后面的一坨就可以用前缀和预处理。
我也不知道狄利克雷卷积怎么算(总不能就这么算吧),反正这样足以通过此题。
预处理时间复杂度 \(\mathcal{O} (n \log \log n)\),分块的时间复杂度 \(\mathcal{O}(\sqrt{n})\),所以总时间复杂度为 \(\mathcal{O}(n \log \log n + T\sqrt{n})\)。
#include <bits/stdc++.h>
#define int long long
#define pii pair< int, int >
#define FRE(x) freopen(x ".in", "r", stdin), freopen(x ".out", "w", stdout)
#define L(i, a, b) for (register int i = (a); i <= (b); i++)
#define R(i, a, b) for (register int i = (a); i >= (b); i--)
#define ALL(x) x.begin(), x.end()
using namespace std;
inline void cmax(int &x, int c) { x = max(x, c); }
inline void cmin(int &x, int c) { x = min(x, c); }
int _test_ = 1;
namespace code {
const int N = 2e7 + 6;
int mu[N], f[N], sum[N], p[N], cnt;
bool vis[N];
void init() {
mu[1] = 1;
L(i, 2, N - 6) {
if (! vis[i]) p[++cnt] = i, mu[i] = -1;
for (int j = 1; j <= cnt && i * p[j] <= N - 6; j++) { // 线性筛,同时预处理 mu
vis[i * p[j]] = 1;
if (i % p[j] == 0) break;
mu[i * p[j]] = (-1) * mu[i];
}
}
L(i, 1, cnt) {
L(j, 1, N - 6) {
if (j * p[i] > N - 6) break;
f[j * p[i]] += mu[j]; // 处理卷积得到的函数
}
}
L(i, 1, N - 6) sum[i] = sum[i - 1] + f[i]; // 前缀和
// L(i, 1, N - 6) cout << f[i] << " ";
}
void clear() {}
void solve() {
int n, m;
cin >> n >> m;
int ans = 0;
if (n > m) swap(n, m);
L(i, 1, n) {
int j = min(n / (n / i), m / (m / i)); // 整除分块
ans += (sum[j] - sum[i - 1]) * (int)(n / i) * (int)(m / i);
i = j;
}
cout << ans << "\n";
}
} // namespace code
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> _test_;
code::init();
L(i, 1, _test_) {
code::clear();
code::solve();
}
return 0;
}
后来听别人说卷积都是这么卷的?

浙公网安备 33010602011771号