传送门:洛谷 CF2072C Creating Keys for StORages Has Become My Main Skill | Codeforces C. Creating Keys for StORages Has Become My Main Skill

更佳的阅读体验:CF2072C 题解


简要题意:构造一个长度为 $n$ 的序列 $a$,使得 $\operatorname{or} \limits_{i = 1}^{n} a_i = x$ 且 $\text{mex}(\{a_1, a_2, a_3, \cdots a_n\})$ 最大,其中 $a \text{ or } b$ 表示 $a$ 与 $b$ 的按位或。

如果不考虑其他条件,要使 $\text{mex}$ 最大,有一个最直接的想法是,从 $0$ 到 $n - 1$ 按顺序填一遍。但此时发现,可能出现 $\operatorname{or} \limits_{i = 1}^{n} a_i \neq x$ 的情况。

可以证明,对于 $0 \sim n - 1$ 的每一个数,贪心地将满足 $x \text{ or } i = x$ 的所有数 $i$ 填入序列中,这样填出来的序列一定是 $\text{mex}$ 最大的。

根据按位或的性质,此时一定有 $x \text{ or }(\operatorname{or} \limits_{i = 1}^{n} a_i) = x$,要想让 $\operatorname{or} \limits_{i = 1}^{n} a_i = x$ 成立,我们只需要在后面继续填至少一个 $x$。

但如果此时序列已经填够了 $n$ 个数,却不满足 $\operatorname{or} \limits_{i = 1}^{n} a_i = x$ 呢?只需要将最后一个数删掉,再填上一个 $x$ 即可。

#include <iostream>
using namespace std;

int t, n, x, sum;
basic_string<int> ans;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    for (cin >> t; t; --t) {
        sum = 0;
        ans.clear();
        cin >> n >> x;
        for (int i = 0; i < n; ++i) if ((sum | i | x) == x) ans += i, sum |= i;
        if (ans.size() == n && sum != x) ans.pop_back();
        while (ans.size() < n) ans += x;
        for (int i = 0; i < n; ++i) cout << ans[i] << " \n"[i == n - 1];
    } return 0;
}
最后修改:2025 年 03 月 03 日
如果觉得我的文章对你有用,请随意赞赏