已完成今日《Nim 游戏与 SG 函数》大学习。
本文比较基础,并未涉及到各种各样的 Nim 游戏,因为笔者比较菜。
1. 公平组合游戏
定义一个游戏为公平组合游戏,当且仅当:
- 双方都知道当前局面的所有信息。
- 每一步的操作与玩家无关。
- 游戏一定在有限步以非平局结束,且同一个状态不可能出现两次。
我们研究公平组合游戏,主要研究先手必胜还是必败。所以定义 \(\mathcal{N}\) 态为(当前手)必胜态,\(\mathcal{P}\) 态为(当前手)必败态。容易发现,无法操作的状态一定是 \(\mathcal{P}\) 态。
注:在游戏的开局,当前手是先手。
这好像是废话。
我们可以把游戏的所有状态画成图,如果 \(X\) 可以一步到 \(Y\),那就连一条 \(X \to Y\) 的有向边。定义这样的图为博弈图。容易发现,对于公平组合游戏,博弈图总是 DAG。
2. Nim 游戏
2.1 Easy Version
现有 \(n\) 个石子,Alice 和 Bob 轮流取 \(i \in [1, 3]\) 个石子(\(i\) 不固定),Alice 先手。无法操作的人失败。何时 Alice 必胜?
什么小奥题。
显然,当 \(4 \nmid n\) 时,Alice 必胜;\(4 \mid n\) 时,Alice 必败。在 \(4 \mid n\) 时,Bob 只需与 Alice 共同拿 \(4\) 个即可。在 \(4 \nmid n\) 时,Alice 先拿 \(n \bmod 4\) 个,这样 Bob 下轮就是 \(\mathcal{P}\) 态。
以 \(n = 6\) 为例,画出博弈图:

注:上图建议搭配 Dark Reader 观看,否则你会看不到边。当然,你可以自己画一个,只有 \(14\) 条边。
红色为 \(\mathcal{P}\) 态,绿色为 \(\mathcal{N}\) 态。观察可以发现:
- \(\mathcal{N}\) 态的后继中一定存在 \(\mathcal{P}\) 态。此时当前手直接走到 \(\mathcal{P}\) 态,就可以让对方必败。
- \(\mathcal{P}\) 态的所有后继一定全为 \(\mathcal{N}\) 态。此时当前手无法走到 \(\mathcal{P}\) 态,就无法让对方必败,那么自己一定必败。
2.2 Medium Version
现有 \(n\) 个石子,Alice 和 Bob 轮流取 \(i \in S\) 个石子(\(i\) 不固定,\(S\) 固定),Alice 先手。无法操作的人失败。何时 Alice 必胜?
这时就没有简单的判定方法了。
考虑给每个状态一个编码,使得所有必败状态的编码相同。很明显,直接令 \(\mathcal{N} \to 1, \mathcal{P} \to 0\) 即可。但是这样扩展性不强,有没有扩展性强的做法呢?
考虑 \(\operatorname{mex}\)[1]。发现当 \(0 \in S\) 时,\(\operatorname{mex}(S) \neq 0\);当 \(0 \not \in S\) 时,\(\operatorname{mex}(S) = 0\)。那么直接把当前状态的后继的编码做一个 \(\operatorname{mex}\) 不就是当前状态的编码吗?于是定义:
显然,必败态的 \(\operatorname{sg}\) 为 \(0\)。判定时,按拓扑序倒序算出每个点的 \(\operatorname{sg}\),然后判定起点的 \(\operatorname{sg}\) 是否为 \(0\) 即可。
定义游戏的 \(\operatorname{sg}\) 为它的初始局面的 \(\operatorname{sg}\)。
2.3 Hard Version
现有 \(n\) 堆石子,第 \(i\) 堆石子有 \(x_i\) 个。Alice 和 Bob 轮流做以下操作:
- 选一堆石子。
- 在那一堆中取走任意多个石子。
Alice 先手,无法操作的人失败。何时 Alice 必胜?
发现这其实是 \(n\) 个 Medium Version 拼到一起。因为可以取走任意多个,所以第 \(i\) 堆的 \(\operatorname{sg}\) 一定为 \(x_i\)。
事实上,Alice 必胜当且仅当 \(\bigoplus \limits_{i = 1}^n x_i \neq 0\)。
证明:若 \(\bigoplus \limits_{i = 1}^n x_i = 0\),此时怎么操作都会让 \(\bigoplus \limits_{i = 1}^n x_i \neq 0\)。假设操作了第 \(i\) 列,发现只有当 \(x_i = \bigoplus \limits_{j \neq i} x_j\) 时 \(\bigoplus \limits_{i = 1}^n x_i = 0\),但是操作后 \(x_i \neq \bigoplus \limits_{j \neq i} x_j\),所以 \(\bigoplus \limits_{i = 1}^n x_i \neq 0\)。
若 \(\bigoplus \limits_{i = 1}^n x_i \neq 0\),此时一定可以操作到 \(\bigoplus \limits_{i = 1}^n x_i = 0\) 的状态。考虑 \(x_i\) 的二进制表示,找到最大的最高位需要变化的 \(x_i\),然后把它减掉一个值,让 \(\bigoplus \limits_{i = 1}^n x_i = 0\)。容易发现,这个值一定存在。\(\square\)
所以我们定义这个游戏的 \(\operatorname{sg}\) 为 \(\bigoplus \limits_{i = 1}^n x_i\)。类似的,设游戏 \(G\) 由互相独立的 \(G_1, G_2, \cdots, G_n\) 组合而成,定义:
定义 \(\operatorname{mex}(S)\) 为最小的不在 \(S\) 内的非负整数。 ↩︎