Nim尼姆博弈

尼姆博弈(Nim Game)

一、问题模型

有 n 堆石子,每堆有若干个。两人轮流操作,每次可以从任意一堆中取走任意多枚石子(至少取 1 枚,可以取完这一堆)。

取走最后一枚石子的人获胜。问:先手是否存在必胜策略?

对应题目:洛谷 P2197 【模板】Nim 游戏

二、结论

把每一堆石子的数量全部异或起来:

  • 如果异或和 != 0,先手必胜(输出 Yes
  • 如果异或和 == 0,先手必败(输出 No

三、为什么是这个结论

设异或和为 S = a1 ^ a2 ^ ... ^ an

情况一:S == 0(必败态)

无论先手从哪一堆取走多少石子,这一堆的数量都会改变,异或和就不再是 0。

也就是说,先手无论如何操作,都会把局面交给后手一个 S != 0 的局面。

情况二:S != 0(必胜态)

先手一定可以找到某一堆,取走若干石子,使新的异或和变成 0。

具体做法:设 S 的最高二进制位是第 k 位,那么一定存在某一堆 ai,它的第 k 位也是 1。把这一堆改成 ai ^ S(显然 ai ^ S < ai,相当于取走了 ai - (ai ^ S) 枚),整体异或和就变成了 0。

之后先手只需要一直模仿后手的操作,把局面重新变回 S == 0,就能保证自己取到最后一枚。

四、AC 代码

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

int main()
{
    int t;
    cin >> t;
    while (t --)
    {
        int n;
        cin >> n;
        int res = 0;
        for (int i = 0; i < n; i ++)
        {
            int cnt;
            cin >> cnt;
            res ^= cnt;
        }
        if (res == 0) cout << "No\n";
        else cout << "Yes\n";
    }
    return 0;
}
posted @ 2026-09-20 15:01  leaderling  阅读(10)  评论(0)    收藏  举报