题解:P9187 [USACO23OPEN] Field Day S

全世界都在研究怎么赢,只有我在大输特输。

如此状态,如何 NOIP?

题面简述

link

给出 \(N\) 个长为 \(C\) 的字符串,每个字符串由 GH 组成,对于每一个字符串,求出它和其它字符串同一位置字符不同的最大值。

解题思路

注意到 \(C\) 仅有 18,我们可以把字符转换成二进制数字,此时问题转化为:求 \(\max_{j = 1}^{n} \text{popcount}(a_i \oplus a_j)\)。其中 \(\text{popcount}\) 为数字在二进制下的位数。

考虑如何求解。我们知道 \(a_i\) 按位取反之后有当前答案最大,为了方便我们设 \(a_i\) 取反后的数为 \(b_i\),如果知道在剩下的数字当中和 \(b_i\) 不同的位数最小的数字为 \(a_j\),此时有 \(C - \text{popcount}(a_j \oplus b_i) = \max_{k = 1}^{n} \text{popcount}(a_i \oplus a_k)\)\(\text{popcount}(a_j \oplus b_i)\) 翻译成人话就是 \(a_j\)\(b_i\) 在二进制下同一位置数字不同的数量。

这其实很好理解,因为每一位只有两种情况,我们又知道 \(a_i\)\(b_i\) 的每一位都不同,此时我们知道有一个 \(a_j\)\(b_i\) 在二进制下共有 \(x\) 位不相同,那么就有 \(a_i\)\(a_j\)\(x\) 位相同,即 \(a_i\)\(a_j\)\(C - x\) 位不同。

现在我们要知道 \(\text{popcount}(a_j \oplus b_i)\) 该怎么做?首先枚举每个 \(a_j\) 肯定不行,但是由于 \(C\) 比较小,也许可以一位一位的考虑。

对于每一个 \(a_i\),我们改变它二进制下某一位上的数字,会得到一个新的数字,再用新的数字重复这个操作,在第 \(x\) 次操作后 \(a_i\) 就会变成 \(b_j\),这个操作数 \(x\) 即为 \(\text{popcount}(a_i \oplus b_j)\),也是 \(b_j\) 变成 \(a_i\) 的最小操作次数。
我们对每一个数都这样做,发现这就是一个 bfs 的过程。这样就可以得到从 \(0\)\(2^C - 1\) 之间的每一个数变成已有数字的最小操作次数,现在我们只需要枚举一遍所有 \(b_i\) 就能求出答案了。

我写还是比较详细的(也许有些啰嗦?)但是可能还是有些抽象,还有不懂的话可以结合代码理解。

代码

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

const int MN = 1e5 + 3;
int C, n;
int a[MN], rec[1 << 18];

queue<pair<int, int> > q;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> C >> n;
    memset(rec, -1, sizeof(rec));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= C; j++) {
            char c;
            cin >> c;
            a[i] = (a[i] << 1) + (c == 'G' ? 0 : 1);
        }
        rec[a[i]] = 0;
        q.push({a[i], 0});
    }

    while (!q.empty()) {
        auto [x, cnt] = q.front();
        q.pop();
        for (int i = 0; i < C; i++) {
            int y = x ^ (1 << i);
            if (rec[y] < 0) q.push({y, rec[y] = cnt + 1});
        }
    }

    for (int i = 1; i <= n; i++)
        cout << C - rec[(1 << C) - 1 - a[i]] << "\n";
    return 0;
}

念念碎

本次模拟赛又双叒叕大 bear 归,非常的心痛,故作此文缓解一下。

你知道的,我没有那么聪明,所以本篇文章是在学习这篇题解后写的,拜谢大佬。

posted @ 2025-11-25 17:29  StarLinkOvO  阅读(2)  评论(0)    收藏  举报