1 条题解
-
0
这是一道最基础、最经典的 博弈论 题目,即 尼姆博弈 (Nim Game)。
1. 算法分析
游戏性质: 这是一个 ICG (Impartial Combinatorial Game,公平组合游戏)。 题目描述的规则( 堆石子,每次取任意数量,取完者胜/无法取者负)完全符合 Nim 游戏 的定义。
Bouton 定理 (Bouton's Theorem): Nim 游戏的状态由所有堆石子数量的 异或和 (XOR Sum) 决定。 设 堆石子的数量分别为 ,定义它们的异或和为:
- 必胜态 (N-position):当 时,先手必胜。
- 必败态 (P-position):当 时,先手必败(即后手必胜)。
定理逻辑简述:
- 目标状态:当所有石子都被取完时,状态为 ,此时异或和 ,这也是必败态(因为轮到谁谁就没法取了)。
- 必胜态可达必败态:如果当前 ,先手一定存在一种取法,使得取完后剩下的石子异或和变为 ,从而把必败态丢给对手。
- 必败态只能去往必胜态:如果当前 ,无论先手怎么取,取完后的异或和一定不为 ,即对手接手的局面一定是必胜态。
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. 复杂度分析
- 时间复杂度:。只需要遍历一遍输入的 个数字进行异或运算。
- 空间复杂度:。只需要常数个变量存储当前读入的数和累积的异或和,不需要数组。
4. 总结
本题是博弈论的入门题,核心只有一句话:Nim 游戏的胜负取决于初始局面石子数的异或和。若异或和非零则先手胜,否则后手胜。
- 1
信息
- ID
- 6156
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者