博弈论基础
博弈论基础
在算法竞赛中,最常见的博弈类型是组合博弈。组合博弈论主要关注以下类型:两人轮流行动的、完美信息(参与者在任意时刻做出决策时,完全了解此前所有事件发生的情况)、无随机因素的博弈。例如,象棋、围棋等都是典型的组合博弈。
——摘自 博弈论简介 - OI Wiki
引入
一般来讲,博弈论题目可以粗略地分为三类做法:
- 直接大力分讨各种状态的最优策略;
- Minimax 搜索和 Alpha-Beta 剪枝;
- 分析 \(\text{SG}\) 函数 / 打表 / 暴搜。
实际上,第一种方法可以被 \(\text{SG}\) 函数形式化表示。
P3150
Alice 和 Bob 玩游戏,Alice 是先手。游戏规则是:有一个数 \(M\),当前玩家需要将 \(M\) 分割为两个数,下一个玩家选择其中一个数再进行分割。无法操作的玩家将输掉游戏。假设 Alice 和 Bob 都绝顶聪明,给出 \(N\) 次游戏的 \(M\),请你判断每局游戏的胜负。\(N \le 50, M \le 10^9.\)
一个状态要么是先手必败态,要么是先手必胜态(因为按照最优策略进行游戏,结果是一定的)。
若一个状态存在一种策略,使得它能进入一个先手必败态,则它是先手必胜态;
若一个状态所有策略均无法进入先手必败态,则它是先手必败态。
我们考虑从终末状态入手:显然,先手必败态是当前的数为 \(1\),也就意味着先手必胜态是选择要分割的数为 \(2\)(分成两个 \(1\) 就可以获胜了)。注意到 \(3\) 只能被分为 \(1 + 2\),所以 \(3\) 是先手必败态;\(4\) 可以被分为 \(1 + 3\),所以 \(4\) 是先手必胜态;以此类推,容易发现,对于选择 \(x\) 来分割,其为先手必胜态当且仅当 \(x\) 为偶数。
证明考虑使用归纳法:假设该结论对 \(1 \sim n\) 都成立,考虑当前数为 \(n + 1\) 时是否成立。若 \(n\) 为偶数,则 \(n + 1\) 为奇数,假设分为两个数 \(x, y\),显然 \(x, y\) 当中恰有一个偶数、一个奇数,根据归纳假设,它们一个为必败态,一个为必胜态,显然后手选择其中的偶数(必胜态)即可获胜,故无论如何划分,当前玩家都会失败,故 \(n + 1\) 为先手必败态;若 \(n\) 为奇数,则 \(n + 1\) 为偶数,此时只需划分为 \((\dfrac{n + 1}{2}, \dfrac{n + 1}{2})\),则后手一定会进入必败态,故 \(n + 1\) 为必胜态。
于是 Alice 必胜当且仅当 \(M\) 为偶数,否则 Bob 必胜。
P4018
Alice 和 Bob 玩游戏,Alice 是先手。游戏规则是:有 \(n\) 个石子,当前玩家可以拿走 \(p^k\) 个(其中 \(p\) 是质数,\(k \ge 0\)),率先把全部石子拿走的玩家获胜。假设 Alice 和 Bob 都绝顶聪明,给出 \(T\) 次游戏的 \(n\),请你判断每局游戏的胜负。\(n \le 5 \times 10^7, T \le 10^5.\)
显然 \(n \in \{p^k\}\) 时先手必胜(其中包含 \(n = 1\) 的情况)。考虑类似筛法,我们将每个必败态 \(x\) 之后的任意后继 \(x + p^k\) 都设为必胜态(因为这表示 \(x + p^k\) 可以通过取走 \(p^k\) 个进入必败态,所以是必胜态),打表后容易观察到:\(x\) 为必败态,当且仅当 \(6 \mid x\)。
证明:仍然考虑归纳法,假设 \(1 \sim n - 1\) 都满足归纳假设,考虑 \(n\) 是否满足。若 \(6 \not\mid n\),则容易发现存在 \(x \in [n - 5, n - 1]\) 满足 \(6 \mid x\)(只需取 \(x = n - (n \bmod 6)\) 即可),并且由于 \(1 = p^0, 2 = 2^1, 3 = 3^1, 4 = 2^2, 5 = 5^1\),所以这些数都是可以取到的,于是 \(n\) 可以转入一个必败态,故 \(n\) 为必胜态;若 \(6 \mid n\),则由于 \(6x\) 一定不是 \(p^k\)(因为至少存在两个质因子),所以 \(n - 6x\) 均无法取到,也就意味着之前的必败态都不能取到,所以 \(n\) 为必败态。
于是只需判断 \(n\) 是否是 \(6\) 的倍数即可。
P9862
Alice 和 Bob 玩游戏,Alice 是先手。游戏规则是这样的:有四种粒子,初始各有若干个,当前玩家需要从给定的 \(5\) 种反应中选择一种进行(每种反应的形式为销毁每种粒子若干个),第一个不能进行反应的玩家失败。假设 Alice 和 Bob 都绝顶聪明,给出 \(n\) 组初始粒子数量,请你判断每局游戏的胜负。\(n \le 100\),每局游戏粒子总个数 \(k \le 30\)。
注意到粒子个数极少,所以我们考虑记忆化暴搜(或 dp)。设状态为 \(S = (a, b, c, d)\) 表示四种粒子分别剩余多少个,那么要判断当前状态是不是必胜态,只需找出所有后继状态中是否有一个必败态,也就是说,设 \(f(S) = 0\) 表示 \(S\) 是先手必败态,\(f(S) = 1\) 表示 \(S\) 是先手必胜态,则有 \(\displaystyle f(S) = 1 - \min_{T \in \text{suc}(S)} f(T)\)。复杂度为 \(O(k^4)\)。
实际上使用 \(\text{SG}\) 函数的定义 \(\displaystyle \text{SG}(S) = \operatorname{mex} \text{SG}(T)\) 是等价的。
Nim 游戏
Nim 游戏的规则是这样的:
共有 \(n\) 堆石子,第 \(i\) 堆有 \(a_i\) 个石子。两名玩家轮流取走任意一堆中的任意多个石子(但不能不取),取走最后一个石子的玩家获胜。
我们定义一个状态 \(S\) 的后继为 \(\text{suc}(S)\),则容易发现,引入中提到的性质可以重新书写如下:
- \(|\text{suc}(S)| = 0\) 的状态 \(S\) 是必败态(没有后继);
- \(S\) 为必胜态,当且仅当 \(\exist T \in \text{suc}(S)\),\(T\) 是必败态;
- \(S\) 为必败态,当且仅当 \(\forall T \in \text{suc}(S)\),\(T\) 是必胜态。
假设我们从 \(S\) 向 \(\text{suc}(S)\) 中的每个状态连有向边,则不难发现在 Nim 游戏下这形成一张 DAG,故我们已经得到了一个 \(O(|V| + |E|)\) 的做法:直接对状态图拓扑排序。但是 Nim 游戏的状态图十分庞大,仅状态数 \(|V|\) 就达到了 \(O(\prod a_i)\),所以这样做是行不通的。
我们给出以下定义:
定义 \(\text{Nim}\) 和 \(\oplus\) 为
这里 \(x, y, a, b\) 均为非负整数。
事实上,这个运算就是二进制下按位异或。
证明:考虑归纳法。假设对于所有 \(a + b \lt x + y\) 的非负整数 \(a, b\),该运算均等价于异或,则:
若 \(x, y\) 的二进制最高位相同,设该位为 \(2^k\),设 \(x = x' + 2^k, y = y' + 2^k\),则 \(x \text{ xor } y = x' \text{ xor } y'\),考察 \(\{a \oplus y \mid a \in [0, x)\}\) 的构成:
当 \(a \in [0, 2^k)\) 时,\(a \oplus y = a \text{ xor }y' + 2^k\),容易发现 \(\{a \text{ xor } y'\} = [0, 2^k)\),那么这部分 \(\{a \oplus y\}\) 实际上等于 \([2^k, 2^{k + 1})\);
当 \(a \in [2^k, x)\) 时,\(a \oplus y = a' \text{ xor } y'\),注意到 \(a'\) 遍取 \([0, x')\),故这部分相当于 \(\{a' \oplus y' \mid a' \in [0, x')\}\)。
同理,我们可以得到 \(\{x \oplus b \mid b \in [0, y)\}\) 由 \([2^k, 2^{k + 1})\) 和 \(\{x' \oplus b' \mid b' \in [0, y')\}\) 两部分组成,容易发现
\[\begin{aligned} x \oplus y &= \text{mex}\{\{a \oplus y \mid a \in [0, x)\} \cup \{x \oplus b \mid b \in [0, y)\}\} \\ &= \text{mex}\{\{a' \oplus y' \mid a' \in [0, x')\} \cup \{x' \oplus b' \mid b' \in [0, y')\} \cup[2^k, 2^{k + 1})\} \\ &= \text{mex}\{\{a' \oplus y' \mid a' \in [0, x')\} \cup \{x' \oplus b' \mid b' \in [0, y')\}\} \\ &= x' \oplus y' = x' \text{ xor } y' = x \text{ xor } y. \end{aligned} \](因为 \(a' \oplus y'\) 和 \(x' \oplus b'\) 均小于 \(2^k\))
若 \(x, y\) 二进制最高位不同,显然该运算满足交换律,故不妨设 \(x = 2^k + x', y \lt 2^k\),则有
\[x \text{ xor } y = 2^k + (x' \text{ xor } y) \]仍然分析两部分集合的组成:
- 当 \(a \in [0, 2^k)\) 时,\(a \oplus y = a \text{ xor } y\),显然这遍取整个 \([0, 2^k)\);
- 当 \(a \in [2^k, x)\) 时,\(a = 2^k + a'\),则 \(a \oplus y = 2^k + (a' \text{ xor } y)\),由于 \(a'\) 遍取 \([0, x')\),故这部分相当于 \(\{a' \oplus y \mid a' \in [0, x')\}\) 向上平移 \(2^k\)。
而另一个集合 \(\{x \oplus b \mid b \in [0, y)\}\) 相当于 \(\{2^k + (x' \oplus b) \mid b \in [0, y)\}\),那么
\[\begin{aligned} x \oplus y &= \text{mex}\{\{a \oplus y \mid a \in [0, x)\} \cup \{x \oplus b \mid b \in [0, y)\}\} \\ &= 2^k + \text{mex}\{\{a' \oplus y \mid a' \in [0, x')\}\cup\{x' \oplus b \mid b \in [0, y)\}\} \\ &= 2^k + (x' \oplus y) = 2^k + (x' \text{ xor } y) = x \text{ xor } y. \end{aligned} \]在 \(x, y \in \{0, 1\}\) 时,容易验证归纳假设成立,故归纳成立。
那么,Nim 游戏有以下结论:
Nim 游戏中,状态 \(S = (a_1, a_2, \dotsb, a_n)\) 为必败态,当且仅当 \(\text{Nim}\) 和
证明:考虑使用归纳法。假设 \(S\) 的所有后继状态均满足性质,则:
若 \(\forall i, a_i = 0\),则 \(S\) 没有后继状态,所以为必败态;
若 \(a_1 \oplus a_2 \oplus \dotsb \oplus a_n = 0\),设取走第 \(i\) 堆的石子,剩下 \(a'_i\) 个,则显然
\[a_1 \oplus a_2 \oplus \dotsb \oplus a_{i - 1} \oplus a_{i + 1} \oplus \dotsb \oplus a_n = a_i \ne a'_i \]故任意后继状态的 \(\text{Nim}\) 和均不为 \(0\),也就是说任意后继状态均为必胜态,故 \(S\) 是必败态;
若 \(a_1 \oplus a_2 \oplus \dotsb \oplus a_n \ne 0\),令该值为 \(x\),则显然存在至少一个 \(a_i\),使得 \(x\) 的二进制为一的最高位也在 \(a_i\) 中出现(否则不能得到该结果),并且有 \(a_i \oplus x \lt a_i\),故只需在第 \(i\) 堆中取走 \(a_i - (a_i \oplus x)\) 个石子即可进入一个必败态,故 \(S\) 为必胜态。
于是我们可以在 \(O(n)\) 时间复杂度内解决一个 \(n\) 堆 Nim 游戏。
P1247
判断 \(n\) 堆 Nim 游戏的胜负性,并且输出先手必胜时第一步的策略(要求“第 \(x\) 堆取走 \(y\) 个”这一操作字典序最小)。
\(n \le 5 \times 10^5, a_i \le 10^9\).
显然只需要使得游戏变为 \(a_1 \oplus a_2 \oplus \dotsb \oplus a_n = 0\),根据我们证明 Nim 游戏结论的过程,只需找到第一个 \(a_i \gt a_i \oplus x\) 的 \(a_i\) 取走 \(a_i - (a_i \oplus x)\) 个即可。
CF15C
有 \(n\) 组石堆,每组有 \(m_i\) 堆,第 \(j\) 堆有 \(x_i + j - 1\) 个石子,你需要判断用所有这些石堆做 Nim 游戏的胜负性。
\(n \le 10^5, 1 \le x_i, m_i \le 10^{16}\)。
最暴力的想法是将区间异或和拆分成考虑每一位的贡献,于是可以变为一个数位 dp。
然而这是一个黄题,所以考虑以下性质:\(\forall k \in \N, 2k \oplus (2k + 1) = 1\)(因为它们只有最低位不同)。于是只需做一些小分讨即可 \(O(1)\) 求出 \(x_i\) 到 \(x_i + m_i - 1\) 的异或和了,于是这个题也就做完了。
P5675
有 \(n\) 堆石子,你需要从中选出若干堆用于 Nim 游戏,并且钦定 Alice(先手)第一次选择哪一堆,求出先手必败的方案数。两个方案不同,当且仅当选择的石堆不同或钦定第一次取的石堆不同(注意钦定第一次取的石堆必须被选出来用于游戏)。\(n \le 200, a_i \le 200\)。
首先若我们选出若干堆异或和为 \(0\),则 Alice 无论第一次选哪堆都必败,所以这部分的方案数是选出的堆数。
接下来考虑选出来的 \(a_i\) 异或和(设为 \(k\))不为 \(0\) 的情况,那么我们需要保证 Alice 第一次选择的那一堆 \(a_j\) 不能使得 \(k\) 变为 \(0\),所以有 \(a_j \lt a_j \oplus k\),也就是说 \(a_j\) 小于其他堆石子的异或和。
注意到第一种情况相当于 \(a_j = a_j \oplus k\),所以我们只需对每个 \(j\),对 \(a_j \le a_j \oplus k\) 的方案数计数。
考虑 dp,设 \(g_{i, k}\) 表示考虑了前 \(i\) 堆,异或和为 \(k\) 的方案数,\(h_{i, k}\) 表示考虑了后 \(i\) 堆,异或和为 \(k\) 的方案数,那么只需枚举断点 \(i\) 表示钦定第一堆选择的石子,再枚举前缀 \([1, i - 1]\) 和后缀 \([i + 1, n]\) 中分别选出的异或和 \(k_1, k_2\),将 \(k_1 \oplus k_2 \ge a_i\) 的答案求和即可。复杂度为 \(O(nV^2)\),\(V = 256\)。
实际上,\(O(V^2)\) 枚举前后缀合并背包相当于在做一个异或 FWT,所以套上 FWT 板子可以做到 \(O(V \log V)\) 对一个断点 \(i\) 求解答案(但是没有必要)。
如果你不会 FWT,可以考虑使用线性基:预处理出前后缀的线性基,在枚举 \(i\) 时暴力合并,假设除去 \(i\) 的 \(n - 1\) 个值组成的线性基大小为 \(k\),则如果线性基能够表示一个数 \(x\),无论 \(x\) 为多少,从这 \(n - 1\) 个值中选出若干个异或得到 \(x\) 的方案数均为 \(2^{n - 1 - k}\)(P4869 albus就是要第一个出场 中亦有记载)。这样做复杂度也为 \(O(nV \log V)\),因为要枚举 \(x\) 并且检查 \(x\) 是否能被线性基表示。
至于为什么上面定义的运算要叫 \(\text{Nim}\) 和,接下来介绍的 \(\text{SG}\) 函数能解释这一点:
\(\text{SG}\) 函数
我们定义一个状态 \(S\) 的 \(\text{SG}\) 函数值为
也就是它所有后继状态的 \(\text{SG}\) 函数值的 \(\text{mex}\),这里 \(\text{mex}(S)\) 表示最小的没有在集合 \(S\) 中出现过的自然数。而状态 \(S\) 为必胜态,当且仅当 \(\text{SG}(S) \ne 0\)。实际上,参考我们在引入部分所做的例题,不难发现这表示我们可以转入一个必败态,所以当前为必胜态。
根据 Sprague-Grundy 理论,可以证明,一个公平组合游戏 \(G\) 一定等价于一个单堆的 Nim 游戏。设 \(G\) 所等价的单堆 Nim 游戏中石子个数为 \(n\),则我们定义 \(G\) 的 \(\text{SG}\) 函数 \(\text{SG}(G) = n\)。容易发现,\(\text{Nim}\) 和就相当于对两个 Nim 游戏求和,由于任意的两个公平游戏 \(G_1, G_2\) 之和所等价的 Nim 游戏即为 \(G_1\) 所等价的 Nim 游戏与 \(G_2\) 所等价的 Nim 游戏之和,所以 \(\text{SG}(G_1 + G_2)\) 应当为 \(\text{SG}(G_1)\) 和 \(\text{SG}(G_2)\) 这两个单堆 Nim 游戏之和,也就是它们的 \(\text{Nim}\) 和,故
实际上根据 Nimber 理论还可以定义 \(\text{Nim}\) 积(Nimber 数系下的乘法),有兴趣可以深入了解(Nim 积)。
由于暴力求解 \(\text{SG}\) 函数的代价一般仍然不可接受,所以常常采用打表找循环节或 dp / 记忆化搜索的办法求解。
AGC017D
有一棵 \(n\) 个节点的树,Alice 和 Bob 玩游戏,Alice 先手,游戏规则是:当前玩家选择一条树上存在的边,把它删掉,使树变成两个连通块,然后删除不包含根节点 \(1\) 的连通块。第一个不能操作的玩家失败。假设 Alice 和 Bob 都绝顶聪明,你需要判断谁将获胜。\(n \le 10^5\)。
考虑树形 dp。设对 \(u\) 子树玩游戏的 \(\text{SG}\) 函数为 \(f_u\),考虑如何转移到父亲(也就是加上一条边)。不难发现,加上了连接到父亲这条边之后,之前的每次操作都可以选择断开这条边然后直接在这个子树游戏中获胜,也就是为之前的每个状态都新增了一个 \(\text{SG} = 0\) 的后继状态,那么 \(f_u\) 由于是 \(\text{mex}\),就会变为 \(f_u + 1\),那么转移就是
于是就做完了。
其他常见公平组合游戏
以下均设 \(f\) 表示 \(\text{SG}\) 函数。
Bachet 游戏
\(n\) 个石子的单堆 Nim 游戏,但是限制每次至多取走 \(k\) 个石子。
结论:先手必败当且仅当 \(n \equiv 0 \pmod {k + 1}\)。
证明:当 \(n \le k\) 时,显然这等价于没有限制的 Nim 游戏,所以 \(f(n) = n\);否则
容易发现 \(f(k + 1) = 0 = f(0), f(k + 2) = 1 = f(1)\),以此类推,容易归纳证明 \(f(n) = n \bmod (k + 1)\)。
ARC168B
\(n\) 堆 Bachet 游戏,你需要找到最大的使得 Alice(先手)必胜的 \(k\),若 \(k\) 可以取无限大则输出 \(-1\)。
\(n \le 2.5 \times 10^5, a_i \le 10^9\)。
\(k\) 为无限大的情况即退化为 Nim 游戏,所以只需先特判掉异或和不为 \(0\) 的情况。
根据 \(\text{SG}\) 函数理论,我们只需保证 \((a_1 \bmod (k + 1)) \oplus (a_2 \bmod (k + 1)) \oplus \dotsb \oplus (a_n \bmod (k + 1)) \ne 0\),首先可以将原本序列中的相同数两两相消,剩下的数互不相同,此时设序列中最大的数为 \(M\),显然 \(k\) 直接取 \(M - 1\) 即可。
k-Nim 游戏
\(n\) 堆 Nim 游戏,但是每次允许从至多 \(k\) 堆里面取石子。
结论:将每堆石子个数用二进制表示,先手必败当且仅当对于每一位,每个数这一位的和对 \(k + 1\) 取模均为 \(0\)。
证明:归纳法。假设对于 \(S = (a_1, a_2, \dotsb, a_n)\),结论对所有 \(T = (b_1, b_2, \dotsb, b_n)\) 满足 \(\sum b_i \lt \sum a_i\) 均成立。下面所说的 \(S\) 的某一位即是所有 \(a_i\) 二进制下该位之和。
- 若 \(S\) 存在至少一位模 \(k + 1\) 不为 \(0\):我们维护当前选出的要取走若干个石子的石子堆集合 \(A\)(在维护 \(A\) 的过程中,我们在加入 \(A\) 时先对每堆取走若干石子,但是预留至少一个石子最后再取走,即,考虑完了每一位后我们再根据下面产生的限制,对每堆再取走 \(\ge 1\) 个石子),初始为空。从高到低考虑 \(S\) 余数不为 \(0\) 的每一位(注意,下述任意取走石子的操作后,我们都重新求解一遍 \(S\) 中每一位的余数):假设当前在考虑第 \(i\) 位,余数为 \(1 \le r_i \le k\),若 \(|A| \ge k + 1 - r_i\),则只需从 \(A\) 中选取 \(k + 1 - r_i\) 堆,钦定它们最终第 \(i\) 位为 \(1\);否则,有 \(r_i \lt k + 1 - |A|\)(也就是 \(r_i \le k - |A|\)),此时还未选取的堆(即 \(S \setminus A\))中有至少 \(r_i\) 堆满足第 \(i\) 位为 \(1\),我们从中选择 \(r_i\) 堆加入 \(A\) 中,并且将它们各先取走若干个石子使得第 \(1 \sim i - 1\) 位均为 \(0\),这时只需钦定原本的 \(|A|\) 堆在最后第 \(i\) 位为 \(0\),且新加入的这 \(r_i\) 堆各需要再取走至少 \(1\) 个石子即可保证最终 \(r'_i = 0\)。不难发现上述过程中,每个钦定都是可满足的(例如,某一堆在考虑第 \(x\) 位时加入,那么我们会先把它取到只剩 \(2^x\) 个并且钦定接下来的操作中至少再取走 \(1\) 个,那么这一堆在所有操作结束后剩下的个数可以是 \([0, 2^x - 1]\) 中的任何数,也就是说第 \(1 \sim x - 1\) 位都是可以任意指定的),并且 \(A\) 集合的大小始终 \(\le k\)(因扩充 \(A\) 时必有 \(r_i + |A| \le k\)),所以上述策略合法。于是我们找到了一种转入每一位余数均为 \(0\) 的策略,根据归纳假设,\(S\) 为必胜态。
- 若 \(S\) 的每一位模 \(k + 1\) 均为 \(0\):显然,任意选择 \(1 \sim k\) 堆取走若干石子的操作都会使得至少一位的余数变为 \(\ne 0\),所以任意操作均将转入必胜态,\(S\) 为必败态。
显然对于 \(S = (0, 0, \dotsb, 0)\) 时,结论成立(为必败态),故归纳成立。
Fibonacci-Nim 游戏
有一堆 \(n\) 个石子,第一个玩家不限制取走的数目(不能不取,也不能取完),随后每个玩家取走的数目不能超过上一个玩家取走数目的两倍,取走最后一个石子的玩家获胜。
结论:先手必败当且仅当 \(n\) 是斐波那契数。
证明:有兴趣可见此处(第二题)。
阶梯 Nim 游戏
有 \(n\) 堆石子,每次操作要么取走第一堆中的若干个石子,要么把第 \(i \gt 1\) 堆石子中的若干个移动到第 \(i - 1\) 堆。取走最后一个石子的玩家获胜。
结论:先手必败,当且仅当奇数堆石子数量的异或和为 \(0\)。
证明:仍然考虑归纳法。假设对于当前状态 \(S\) 的所有后继状态,结论均成立,考虑 \(S\) 的奇数堆情况:若 \(S\) 奇数堆异或和 \(k \ne 0\),那么先手可以看作是在玩一个只有奇数堆石子构成的 Nim 游戏,将第 \(i\) 堆的若干石子移到第 \(i - 1\) 堆可以看作是取走第 \(i\) 堆的若干石子(因我们不考虑后继状态的偶数堆情况),所以只需根据 Nim 游戏先手必胜时的操作策略,找到一个 \(a_i \oplus k \lt a_i\) 的堆即可;若 \(S\) 奇数堆异或和为 \(0\),则先手不能操作偶数堆,因为无论先手从某个偶数堆移动多少个石子进入上一堆,后手都可以把刚才移过来的石子移动到上上堆(即上一个偶数堆,如果上一堆已经是第一堆,那么后手直接取走这些石子即可),从而转入一个先手必败态,于是先手只能操作奇数堆,根据我们刚才的观察,这相当于在玩一个只有奇数堆的 Nim 游戏,于是先手此时为必败。
P2575
Alice 和 Bob 玩游戏,Alice 是先手。游戏规则是:有一个 \(n \times 20\) 的棋盘,上面有若干个棋子,对于一个棋子,如果右边有空位,则可以将它移动到右侧第一个空位里,否则不能移动。率先不能移动棋子的玩家输掉游戏。假设 Alice 和 Bob 都绝顶聪明,给出 \(T\) 次游戏的初始情况,你需要判断 Alice 能否获胜。
\(n \le 1000, T \le 100\)。
显然行与行之间是互不影响的,所以可以认为这是 \(n\) 个长度为 \(m = 20\) 的单行游戏的和。最直观的想法就是暴搜出单行游戏所有状态的 SG 函数值,这样复杂度为 \(O(m2^m + Tnm)\),实际上可以直接通过本题。
// 将棋盘左右翻转,方便使用位运算找空位
#define lowbit(x) (x & (-x))
constexpr int N = 20, Full = (1 << N) - 1;
int SG[Full + 3];
inline int dfs(int S) {
if(SG[S] != -1) return SG[S];
if(!__builtin_popcount(S)) return SG[S] = 0;
int T = Full ^ S, ptr = 1, cur = S;
vector<int> buc(23, 0);
for(; cur; cur ^= lowbit(cur)) {
int lbt = lowbit(cur);
for(; ptr < lbt; ptr <<= 1)
if(T & ptr) T ^= ptr;
if(!T) break;
int val = dfs(S ^ lowbit(T) ^ lbt);
if(val <= N + 1) ++buc[val];
}
for(int i = 0; i <= N + 2; ++i)
if(!buc[i]) { SG[S] = i; break; }
return SG[S];
}
考虑在一行的开头新增一个空格。由于空格的总数不变,考虑定义空格数为石子堆数,每个空格对应的石子数就是它到下一个空格之间的棋子数量,对于连续的一段棋子,操作其中从右往左数第 \(i\) 个棋子就表示移动 \(i\) 个石子到下一堆,而移动到最右侧紧密放置(不能再移动)就表示从第一堆石子中取走了,于是单行的游戏转化为了一个阶梯 Nim,那么只需根据上面的转化求出奇数堆石子数量的异或和即可。这样复杂度为 \(O(Tnm)\)。
P3480
Alice 和 Bob 玩游戏,Alice 是先手。游戏规则是:给出 \(n\) 堆石子,满足 \(\forall i \ge 2, a_i \ge a_{i - 1}\),也就是每一堆数量不少于前一堆。每次操作可以从一堆石子中取走任意多个石子,但是需要保证石子数仍然不降。无法取走石子的玩家输掉游戏。假设 Alice 和 Bob 都绝顶聪明,给出 \(T\) 次游戏的初始情况,你需要判断 Alice 能否获胜。
\(n \le 1000, T \le 10\),对于每个游戏,\(\sum a_i \le 1000\)。
考虑差分数组:\(b_1 = a_1, b_i = a_{i} - a_{i - 1}\),则从第 \(1 \le i \lt n\) 堆取走 \(d\) 个石子,\(b\) 发生的变化为 \(b_i \to b_{i} - d, b_{i + 1} \to b_{i + 1} + d\);从第 \(n\) 堆取走 \(d\) 个石子,则 \(b_n \to b_n - d\)。操作期间需要保证 \(\forall i, b_i \ge 0\)。容易发现这就是翻转了一次的阶梯 Nim 游戏,所以求出 reverse 后的差分数组奇数位置的石子数异或和即可。
P5363
Alice 和 Bob 玩游戏,Alice 是先手。游戏规则是:有一个长为 \(n\) 的长条状棋盘,上面有 \(m\) 个棋子,每个格子至多有一个棋子,每次操作可以选择一个棋子向左移动若干格,但不能跨过其他棋子。不能移动棋子的玩家输掉游戏。假设 Alice 和 Bob 都绝顶聪明,给出 \(n, m\),你需要求出有多少种 Alice 能获胜的初始状态。答案对 \(10^9 + 9\) 取模。
\(n \le 1.5 \times 10^5, m \le 50\)。
设 \(p_i\) 表示第 \(i\) 个棋子的位置,那么把第 \(i\) 个棋子左移 \(d\) 格,将会导致它与第 \(i - 1\) 个棋子间距减少 \(d\),与第 \(i + 1\) 个棋子间距增加 \(d\),容易发现这与上一道题相同:我们设 \(dis_i = p_i - p_{i - 1}\)(\(p_0 = 0\)),那么相当于石子数依次为 \(dis_{m}, dis_{m - 1}, \dotsb, dis_{1}\) 的一个阶梯 Nim 游戏。
总状态数显然是 \(\dbinom{n}{m}\),考虑从中减去必败态。于是现在需要对奇数位置异或和为 0 的状态计数,也就是对满足 \(\sum_{i = 1}^{m} b_i \le n\),\(\forall i, b_i \ge 1\),且 \(\bigoplus_{i = 1}^{(m + 1)/2} b_{2i - 1} = 0\) 的长为 \(m\) 的数组 \(b\) 计数。
考虑 dp,由于偶数位置可以最后再填(插板法即可),所以我们给偶数位置每个至少预留一个空位,那么 dp 时只考虑奇数位置,并且奇数位置的总和不多于 \(n\) 减去偶数位置的个数。设考虑了二进制前 \(i\) 位,这些位异或和都为 0(也就是说这些位为 1 的个数都是偶数),当前 \(b\) 数组奇数位置的和为 \(j\) 的方案数为 \(f_{i, j}\),转移时枚举给奇数位置分配 \(k\) 个 \(2^{i}\)(必须有 \(2 \mid k\)),大概形如 \(\dbinom{\lfloor \frac{m + 1}{2} \rfloor}{k}f_{i, j - k \times 2^i} \to f_{i + 1, j}\)。复杂度为 \(O(nm \log n)\)。
威佐夫 (Wythoff) 游戏
有 2 堆石子,每次操作从其中一堆或两堆中取若干个石子,若选两堆,则必须取走相同多个石子。取走最后一个石子的玩家获胜。
先考虑打表,可以发现以下规律:首先由于两堆不区分,所以不妨令 \(a_1 \lt a_2\),设第 \(i\) 个必败态为 \((a_{i, 1}, a_{i, 2})\),则 \(a_{i, 1} = \operatorname{mex} \bigcup_{j = 1}^{i - 1}\{a_{j, 1}, a_{j, 2}\}\),\(a_{i, 2} = a_{i, 1} + i\)。但是直接这样做时间复杂度不够优秀。
结论:不妨令 \(a_1 \lt a_2\),先手必败当且仅当 \(a_1 = \lfloor (a_2 - a_1) \phi \rfloor\),其中 \(\phi = \dfrac{\sqrt 5 + 1}{2}\)。
要证明这个结论,需要用到以下定理:
定理1(Beatty 定理):定义一个无理数 \(x\) 生成的 Beatty 序列为 \(B_x = \{\lfloor kx \rfloor : k \in \N^+\}\)。对于无理数 \(x, y\),若 \(\dfrac{1}{x} + \dfrac{1}{y} = 1\),则 \(B_x\) 和 \(B_y\) 构成 \(\N^+\) 的一个分划,也即 \(B_x \cap B_y = \emptyset, B_x \cup B_y = \N^+\)。此时也称 \(B_x\) 和 \(B_y\) 为互补 Beatty 序列。
设 \(A_x = \{kx : k \in \N^+\}\),我们将 \(A_x\) 和 \(A_y\) 归并起来得到一个序列 \(\{a_i\}\)。
现在我们证明 \(\{a_i\}\) 中没有重复元素:假设存在 \(a_i = a_{i + 1}\),不妨令 \(a_i \in A_x, a_{i + 1} \in A_y\),则有
此时我们并不知道右边是不是无理数。但是,由于 \(\dfrac{1}{x} + \dfrac{1}{y} = 1\),故 \(\dfrac{1}{y} = 1 - \dfrac{1}{x}\),代入有
这样,等式左边为有理数(因其为整分数),右边为无理数,这就产生了矛盾。所以 \(\{a_i\}\) 中没有重复元素。
需要证明的是 \(\lfloor a_i \rfloor = i\),注意到 \(a_i\) 是序列第 \(i\) 小的数,那么我们只需说明 \(a_i\) 是序列第 \(\lfloor a_i \rfloor\) 小的数,也就是 \(\{a_i\}\) 中小于等于 \(a_i\) 的数恰好有 \(\lfloor a_i \rfloor\) 个。不妨令 \(a_i \in A_x\),则 \(a_i = k_1x\),那么 \(A_x\) 贡献了 \(k_1\) 个小于等于 \(a_i\) 的数,\(A_y\) 贡献了 \(\left\lfloor \dfrac{k_1x}{y} \right\rfloor\) 个,则
于是我们知道了 \(\{\lfloor a_i \rfloor\} = \N^+\),也就是 \(B_x \cup B_y = \N^+\)。另外,由于 \(\lfloor a_i \rfloor\) 互不相同,所以 \(B_x \cap B_y = \emptyset\)。故 \(B_x, B_y\) 构成正整数集 \(\N^+\) 的一个分划。
现在我们根据 Beatty 定理给出上述结论的证明:
证明:考虑归纳法,假设对于所有 \(b_2 - b_1 \lt a_2 - a_1\) 的 \((b_1, b_2)\) 结论均成立。
若 \(a_1 = \lfloor (a_2 - a_1)\phi \rfloor\),此时 \(a_2 = a_1 + (a_2 - a_1) = \lfloor (a_2 - a_1)(\phi + 1) \rfloor\),即 \(a_1 \in B_{\phi}, a_2 \in B_{\phi + 1}\), 由于 \(\dfrac{1}{\phi} + \dfrac{1}{\phi + 1} = 1\),故 \(B_{\phi}\) 与 \(B_{\phi + 1}\) 互补。此时如果要转入必败态,就要求操作后 \(a'_1 = \lfloor t\phi \rfloor, a_2' = \lfloor t(\phi + 1) \rfloor\),其中 \(t \lt a_2 - a_1\)。显然,从 \(a_1\) 或 \(a_2\) 中取走若干石子均不能实现这一点,所以只能考虑从两堆中同时取走若干个石子。注意到 \(t = a_2' - a_1' \lt a_2 - a_1\),所以这种操作也无法转入必败态,故当 \(a_1 = \lfloor (a_2 - a_1)\phi \rfloor\) 时,先手必败。
若 \(a_1 \ne \lfloor (a_2 - a_1)\phi \rfloor\),令 \(k = a_2 - a_1\),若 \(a_1 \gt \lfloor k\phi \rfloor\),则先手只需从两堆同时取走 \(a_1 - \lfloor k\phi \rfloor\) 个石子,状态即变为 \((\lfloor k\phi \rfloor, \lfloor k\phi \rfloor + k)\),也就是 \((a_1', a_2') = (\lfloor (a'_2 - a'_1)\phi \rfloor, \lfloor (a'_2 - a'_1)(\phi + 1) \rfloor)\),根据归纳假设,这是必败态;若 \(a_1 \lt \lfloor k\phi \rfloor\),由于 \(B_{\phi}\) 和 \(B_{\phi + 1}\) 形成 \(\N^+\) 的分划,所以 \(a_1\) 一定出现在某个必败状态 \((a_1, a_2')\) 中(可能不是作为第一堆)。假设 \(a_1\) 作为第一堆出现,那么有 \(a_1 = \lfloor t\phi \rfloor\),此时有 \(a_2' = a_1 + t\),那么只需从现在的 \(a_2\) 中取走 \(k - t\) 个即可;否则,有 \(a_1 = \lfloor t(\phi + 1) \rfloor\),此时 \(a_2' = \lfloor t\phi \rfloor = a_1 - t\),那么只需从现在的 \(a_2\) 中取走 \(k + t\) 个。于是,总是存在一种策略从当前状态转入必败态,所以此时为先手必胜。
由于 \(d = a_2 - a_1 = 1\) 时(此时状态为 \((1, 2)\))结论成立,所以归纳成立。
一般图博弈
有一张无向图 \(G = (V, E)\),和一个指示节点 \(u\),当前局面表述为 \((V, E, u)\)。两个玩家轮流行动,每次操作需要选择一个与 \(u\) 相邻的节点 \(v\)(即 \((u, v) \in E\)),并且将局面变为 \((V \setminus \{u\}, E \setminus \{(u, v) \mid v \in N(u)\}, v)\),也就是从点集中删除 \(u\),从边集中删除所有与 \(u\) 相关的边,并且将指示节点移动到 \(v\)。若当前玩家不能选择出一个合法的 \(v\)(也就是说 \(|N(u)| = 0\)),则该玩家输掉游戏。
结论:先手必胜,当且仅当指示节点 \(u\) 出现在图 \(G\) 的所有最大匹配中。
证明:考虑归纳法,假设 \(G\) 的所有子图 \(G'\) 都满足上述结论。
当 \(u\) 满足上述性质时,设 \(G\) 的一个最大匹配为 \(M\),此时,先手可以将指示节点移动到在 \(M\) 中与 \(u\) 匹配的节点 \(v\)。由于 \(u\) 出现在所有 \(M\) 中,故残余图 \(G' = (V \setminus \{u\}, E \setminus \{(u, v) \mid v \in N(u)\})\) 的最大匹配不大于 \(|M| - 1\);且 \(M \setminus (u, v)\) 为 \(G'\) 的一个大小为 \(|M| - 1\) 的匹配,故它为 \(G'\) 的一个最大匹配。然而,后手面临的指示节点为 \(v\),此时不在匹配 \(M \setminus (u, v)\) 中,故 \(v\) 不出现在 \(G'\) 的所有最大匹配中,根据归纳假设,后手面临一个必败态。
当 \(u\) 不出现在所有最大匹配中时,对于所有不包含 \(u\) 的最大匹配 \(M\),有 \(\forall v \in N(u), v \in M\),也就是说 \(u\) 的所有相邻节点都在 \(M\) 中(否则可以加入 \((u, v)\) 这条边使得 \(M\) 变大),且删除 \(u\) 及含 \(u\) 的边集后,\(M\) 不改变,也就是说残余图 \(G'\) 的最大匹配大小不变;而对于包含 \(u\) 的最大匹配,删除 \(u\) 后它们便不是最大匹配了。显然,删除 \(u\) 不会产生新的最大匹配,所以 \(G'\) 的最大匹配为先前不包含 \(u\) 的所有最大匹配,并且无论先手选择了哪个 \(v \in N(u)\),都有 \(v\) 位于所有这些最大匹配中,于是先手只能转入必胜态,则当前状态为先手必败。
由于一般图的匹配不太好求,所以一般是以二分图的形式给出的博弈。
例题:
P1971 [NOI2011] 兔兔与蛋蛋游戏
啊写起来好累啊,等会再写把.jpg
HDU3446
给出一张 \(n \times m\) 的棋盘,有一些位置
#不能走,其它的.可以走,有一个王会被放在给定的地方K,每一步可以走的范围如下图:
走过的格子不能再走。现在 Alice 和 Bob 轮流按最优策略操作,不能移动的人就输了,问谁会获得胜利。\(n,m \le 15\)。
直接连边,先去掉 \(K\) 跑一般图最大匹配,若 \(K\) 会出现在所有最大匹配中,则加入 \(K\) 后会形成一条增广路(当然你也可以在没有 \(K\) 和有 \(K\) 的图上跑两次最大匹配)。
(关于一般图最大匹配:带花树 - 洛谷专栏)
反常 Nim 游戏
\(n\) 堆石子,每次取走一堆中的任意多个,取走最后一个石子的玩家失败。
结论:状态 \(S = (a_1, a_2, \dotsb, a_n)\) 为先手必败,当且仅当:
-
存在 \(i\) 使得 \(a_i \gt 1\),且 \(a_1 \oplus a_2 \oplus \dotsb \oplus a_n = 0\);
-
或,对于所有 \(i\) 都有 \(a_i \le 1\),且 \(a_1 \oplus a_2 \oplus \dotsb \oplus a_n = 1\)。


浙公网安备 33010602011771号