NOI 2025 见!

 

短短题解:CF1750D Count GCD

题目链接

把要求的 \(\gcd(b_1, b_2, \dots, b_i) = a_i\) 写成 \(\gcd(\gcd(b_1, b_2, \dots, b_{i-1}), b_i) = a_i\),这等价于要求 \(\gcd(a_{i - 1}, b_i) = a_i\),其中定义 \(a_0\)\(\gcd\) 的单位元;这就已经是充要的了。

\(\gcd(a_{i - 1}, b_i) = a_i\) 做观察:

  • \[\gcd(a_{i-1}, b_i) = a_i \implies a_i \mid a_{i-1} \land a_i \mid b_i \]

  • \[\gcd(a_{i-1}, b_i) = a_i \iff \gcd(\frac{a_{i-1}}{a_i}, \frac{b_i}{a_i}) = 1 \]

因此对于 \(2 \leq i \leq n\) 的每个 \(i\),必须都有 \(a_{i} \mid a_{i-1}\),否则不存在任何符合条件的 \(b\) 序列,直接输出 0

接下来是计数:满足 \(b_1 = a_1\),且对于 \(2 \leq i \leq n\) 的每个 \(i\),有 \(1 \leq b_i \leq m\)\(\gcd(\frac{a_{i-1}}{a_i}, \frac{b_i}{a_i}) = 1\) 的序列 \(b\) 的个数。

注意到在位置 \(i\)\(b_i\) 的合法性与其他位置 \(j\)\(b_j\) 均无关,因此可以使用乘法原理合并每个位置上的答案。

做点简化,设 \(\frac{a_{i-1}}{a_i}\)\(x\)\(\frac{b_i}{a_i}\)\(y\)。问题即变为统计满足 \(1 \leq y \cdot a_i \leq m\),即 \(1 \leq y \leq \lfloor \frac{m}{a_i} \rfloor\)\(\gcd(x, y) = 1\)\(y\) 的个数。

这是莫比乌斯反演例题:

\[\begin{aligned} \sum_{y=1}^{\left\lfloor \frac{m}{a_i} \right\rfloor} [\gcd(x, y) = 1] &= \sum_{y=1}^{\left\lfloor \frac{m}{a_i} \right\rfloor} \sum_{d \mid \gcd(x, y)} \mu(d) \\[6pt] &= \sum_{y=1}^{\left\lfloor \frac{m}{a_i} \right\rfloor} \sum_{\substack{d \mid x \\ d \mid y}} \mu(d) \\[6pt] &= \sum_{y=1}^{\left\lfloor \frac{m}{a_i} \right\rfloor} \sum_{d \mid x} \mu(d)\,[d \mid y] \\[6pt] &= \sum_{d \mid x} \mu(d) \sum_{y=1}^{\left\lfloor \frac{m}{a_i} \right\rfloor} [d \mid y] \\[6pt] &= \sum_{d \mid x} \mu(d) \left\lfloor \frac{\left\lfloor \frac{m}{a_i} \right\rfloor}{d} \right\rfloor \end{aligned} \]

#include <bits/stdc++.h>
using namespace std;

constexpr int N = 200000 + 1, P = 998244353;

int a[N];

void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }

    auto getprms = [](int x) {
        vector<int> res;
        for (int i = 2; i * i <= x; ++i) if (x % i == 0) {
            x /= i;
            res.push_back(i);
            while (x % i == 0) {
                x /= i;
            }
        }
        if (x != 1) {
            res.push_back(x);
        }
        return res;
    };

    int ans = 1;
    for (int i = 2; i <= n; ++i) {
        if (a[i - 1] % a[i]) {
            cout << "0\n";
            return ;
        }

        vector<int> res = getprms(a[i - 1] / a[i]);
        int sm = 0;
        auto dfs = [&](auto &&self, int dep, int mul, int mu) {
            if (dep == (int)res.size()) {
                sm += m / a[i] / mul * mu;
                return ;
            }
            self(self, dep + 1, mul, mu);
            self(self, dep + 1, mul * res[dep], -mu);
        };
        dfs(dfs, 0, 1, 1);
        ans = (long long)ans * sm % P;
    }
    cout << ans << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}

posted on 2026-01-04 10:06  SkyWave2022  阅读(2)  评论(0)    收藏  举报

导航