1 条题解

  • 0
    @ 2026-10-26 5:35:26

    思路与算法

    这是正常玩法的Nim:每次只改变一堆,取任意正数,轮到时无石子者负。把所有堆大小异或得到 S=X1⊕⋯⊕XNS=X_1\oplus\cdots\oplus X_N。S=0S=0 输出lose,否则输出win。只需逐项读入并累计异或,不必保存全部石子数。

    异或逐位记录1的奇偶。非零时,找到 SS 的最高非零位,在这一位为1的一堆 xx 上改为 y=x⊕Sy=x\oplus S。最高位由1变0且更高位不变,因此 0≤y<x0\le y<x,这是合法取走若干石子的操作,操作后全局异或变0。

    正确性说明

    全空局面的异或为0,且轮到者败。从异或0的局面改变一堆 xx 为不同的 y<xy<x 后,异或成为 x⊕y≠0x\oplus y\ne0,无法一步保持零。反之,非零局面按最高位构造,总能合法走到异或0。

    游戏总石子数每步严格减少,故没有循环或和局。对总石子数归纳,零异或局面的全部后继必胜,所以它必败;非零局面存在零异或败后继,所以它必胜。因此累计异或的判定及输出正确。

    复杂度

    累计量初始化 O(1)O(1),读入每堆做一次异或,共 O(N)O(N) 时间;额外空间 O(1)O(1)。不按总石子数展开状态,也不保存全部堆。

    易错点

    1. 每次只能取一堆,与同时改多堆、取光者输的版本不同。
    2. 异或不是按位或,也不是普通总和;相同堆成偶数对时异或抵消。
    3. 输出必须是小写win/lose。正式选点中堆初始大小均为正,空局面仅是策略证明的内部终态。
    4. 覆盖一堆、非零石子却零异或、最多50000堆及最大堆值。含初始零堆大小而违反当前源Xi≥1的公开整点已排除。
    5. 独立答案逐位统计奇偶,不调用异或判定,并与340个完整小规模极小化极大博弈核对。数据非官方原版。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, value = 0;
        cin >> n;
        for (int i = 0; i < n; i++) {
            int pile;
            cin >> pile;
            value ^= pile;
        }
        cout << (value ? "win" : "lose") << '\n';
    }
    
    • 1

    信息

    ID
    1673
    时间
    1000ms
    内存
    512MiB
    难度
    普及
    标签
    递交数
    1
    已通过
    1
    上传者