1 条题解

  • 0
    @ 2025-12-11 22:00:55

    这是一道最基础、最经典的 博弈论 题目,即 尼姆博弈 (Nim Game)

    1. 算法分析

    游戏性质: 这是一个 ICG (Impartial Combinatorial Game,公平组合游戏)。 题目描述的规则(NN 堆石子,每次取任意数量,取完者胜/无法取者负)完全符合 Nim 游戏 的定义。

    Bouton 定理 (Bouton's Theorem): Nim 游戏的状态由所有堆石子数量的 异或和 (XOR Sum) 决定。 设 NN 堆石子的数量分别为 X1,X2,,XnX_1, X_2, \dots, X_n,定义它们的异或和为:

    S=X1X2XnS = X_1 \oplus X_2 \oplus \dots \oplus X_n
    • 必胜态 (N-position):当 S0S \neq 0 时,先手必胜。
    • 必败态 (P-position):当 S=0S = 0 时,先手必败(即后手必胜)。

    定理逻辑简述:

    1. 目标状态:当所有石子都被取完时,状态为 (0,0,,0)(0, 0, \dots, 0),此时异或和 S=0S=0,这也是必败态(因为轮到谁谁就没法取了)。
    2. 必胜态可达必败态:如果当前 S0S \neq 0,先手一定存在一种取法,使得取完后剩下的石子异或和变为 00,从而把必败态丢给对手。
    3. 必败态只能去往必胜态:如果当前 S=0S = 0,无论先手怎么取,取完后的异或和一定不为 00,即对手接手的局面一定是必胜态。

    2. 代码逻辑解析

    这份代码非常简洁,直接实现了上述定理。

    #include <cstdio>
    
    int n, a, x;
    
    // 快速读入模板,用于加速输入
    inline int read() {
        int s = 0, w = 1;
        char ch = getchar();
        while (ch < '0' || ch > '9') {
            if (ch == '-') w = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9')
            s = s * 10 + ch - '0', ch = getchar();
        return s * w;
    }
    
    int main() {
        // 读入堆数
        n = read();
    
        // a 用于存储异或和,全局变量默认初始化为 0
        // 循环读入每一堆的数量 x,并计算异或和
        while (n--) {
            x = read();
            a ^= x; // a = a XOR x
        }
    
        // 根据异或和结果判断胜负
        // 如果 a != 0 (true),输出 "win" (先手胜)
        // 如果 a == 0 (false),输出 "lose" (先手败)
        puts(a ? "win" : "lose");
    }
    

    3. 复杂度分析

    • 时间复杂度O(N)O(N)。只需要遍历一遍输入的 NN 个数字进行异或运算。
    • 空间复杂度O(1)O(1)。只需要常数个变量存储当前读入的数和累积的异或和,不需要数组。

    4. 总结

    本题是博弈论的入门题,核心只有一句话:Nim 游戏的胜负取决于初始局面石子数的异或和。若异或和非零则先手胜,否则后手胜。

    • 1

    信息

    ID
    6156
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者