「博弈论学习笔记」#1 组合游戏基础

OI 中的博弈论主要研究公平组合游戏(ICG)。

此外还有非公平组合游戏,比如大部分的棋类;反常游戏,ICG中的胜者改为败者。

公平组合游戏

定义

如果一个游戏满足以下条件,就称其为一个公平组合游戏

  1. 由两名玩家交替行动。
  2. 在游戏的任意时刻,能执行的合法操作与当前是那一名玩家无关。
  3. 先无法行动者告负。

同时公平组合游戏一定只有先手必胜和先手必败两种情况。

Bash Game

Bash 游戏形式如下

\(n\) 个石子,两人博弈,每人每次可以拿 \(1 \sim m\) 个石子,无法拿石子的人告负。给定 \(n\)\(m\),求先手是否必胜。

  • \(n \le m\),那么先手直接全部拿走即可,必胜。
  • \(n = m+1\),那么先手不能一次都拿走且后手一定能全部拿走,先手必败。

将上述情况进行扩展,如果 \(m+1 \mid n\),那么若先手拿走 \(k\) 个,后手只要拿走 \(m+1-k\) 个,那么仍然满足 \(m+1 \mid n\)。由于当 \(n=0\)\(m+1 \mid n\),所以如此循环往复下去先手一定会面临 \(n=0\) 的局面,所以先手必败。

否则先手只要取 \(k\) 个使得 \(m+1 \mid n-k\),就能回到上述状态,只不过上面的「先手」是现在的后手,其必败,所以这种情况先手必胜。

luogu4018

题面

将上题取 \(1 \sim m\) 个改为取任意能表示为 \(p^k\) 的数个,其中 \(p\) 是质数且 \(k \in \mathbb{N^+}\),同时 \(p^k\) 小于等于当前剩余石子数。

考虑 \(n \in [1,5]\) 时,先手都可以一次取完。

而当 \(n=6\) 时则不能。

由唯一分解定理容易发现任何 \(6\) 的倍数都不能写成 \(p^k\) 的形式。

所以仿照上述操作,如果 \(6 \mid n\),那么先手一定无法取 \(6\) 的倍数个,而后手一定能使得两次取走 \(6\) 的倍数个,所以此时先手必败。

否则先手将 \(n\) 取成 \(6\) 的倍数个即可,必胜。

Nim Game

\(n\) 堆石头,第 \(i\) 堆有 \(a_i\) 个石子。两名玩家博弈,每次可以选择一堆并取走其中任意非 \(0\) 个石子,无法取石子者告负。判断先手必胜还是必败。

定理:

Nim游戏先手必胜,当且仅当 \(\bigoplus_{i=1}^n a_i \neq 0\),也就是 nim 和为 \(0\)

证明:

所有石子被取走的局面是失败局面,此时 nim 和为 \(0\)。考虑一个 nim 和 \(x\) 不为 \(0\) 的情况,那么设 \(x\) 最高为的 \(1\) 在第 \(k\) 位,一定存在至少一个 \(a_i\) 满足第 \(k\) 位为 \(1\)。设它为 \(a_j\),那么有 \(a_j \oplus x < a_j\),而 \(a_j \oplus x\)\(x \oplus a_j\) 做异或运算为 \(0\),其中后者表示 nim 和除掉 \(a_j\)。因此只要让 \(a_j\) 变成 \(a_j \oplus x\) 就能使得 nim 和为 \(0\),而后者小于前者,因此可以通过一次操作使得 nim 和为 \(0\)

如此重复,一定能使得后手只会面临 nim 和为 \(0\) 的局面,最终到无法取走石子。

hdu1850

Nim 游戏,先手第一次操作有多少种必胜方法。

仿照证明过程,如果 nim 和不为 \(0\),那么任意选择一个 \(a_i \oplus x < a_i\) 的就行

有向图游戏与 SG 函数

有向图游戏

给定一个 DAG,形式化地写作 \(G(X,F)\),其中点集 \(X\) 为局面集合,\(F\)\(X\) 上的函数,对于节点 \(x \in X\)\(F(x)\) 表示从其出发能够一步移动到的位置集合,表示了一个形式上的边集。如果 \(F(x) = \varnothing\),那么称 \(x\) 为终点,如果 \(y\) 不属于任何一个 \(F(x)\),那么称其为起点。

两人轮流移动初始在起点的一枚棋子,若其在 \(x_0\),那么可以移动到 \(F(x_0)\) 内的任意节点。无法移动者告负。

任何一个 ICG 都能转化成有向图游戏,具体方法是将每个局面都带入点集 \(X\),从局面 \(x\) 能到达的局面集合构成 \(F(x)\)。由 ICG 的定义可知其不可能存在环,若存在环则游戏一定存在平局。

上文有一些很奇妙的内容。

我们能通过考虑小范围的胜负情况来让大范围的状态归约到它们上;失败局面可以倒推出先手必败局面;本来是先手必败的状态,经过一次操作之后就变成先手必胜了。

把这一切放到图上就容易理解了。由于 ICG 只有先手必胜局面和先手必败局面,所以每个节点(状态)都是必胜或必败状态之一。而且状态可以转化,对于 \(x\)\(F(x)\) 都是他的「子游戏」,二者之间相差一次操作。所以对于一条从终点倒推向起点的链,其节点状态必然是必败,必胜,必败,必胜。在一张图上,一个节点连到的点,他们到终点的长度不一样,自然有必胜也有必败。

比较简单的情况就是如果 \(F(x)\) 都是必败局面,那么无论怎么操作 \(x\),对方都一定面临必败局面,所以是必胜;反过来也一样。

但考虑到二者绝顶聪明,只要 \(F(x)\) 中又一个必败局面,当前玩家一定会这样操作。而如果 \(F(x)\) 中存在一个必胜局面,玩家绝对不会这样做。所以只有 \(F(x)\) 全都是必胜局面,\(x\) 才是必败局面。

此时引入概念后继状态。对于 \(x\),其后继状态为 \(F(x)\),在图上也可称后继节点。

SG 函数

定义 \[ SG(x)= \operatorname{mex} \big\{ SG(y) | y \in F(x) \big\} \] 也就是 \(x\) 所有后继状态的 \(SG\) 函数值中没有出现过的最小非负整数。

整个游戏的 \(SG\) 函数值为起点的 \(SG\) 函数值。

特殊规定终点的 \(SG\) 函数值为 \(0\),同时要保证必败局面的 \(SG\) 函数值都为 \(0\)

如果存在一个 \(SG(x) > 0\),那么 \(x\) 的后继状态中一定存在 \(SG\) 函数值为 \(0\) 的状态,也就是存在必败局面,此时 \(x\) 为必胜局面。否则 \(SG(x)=0\),那么 \(x\) 的后继状态中一定不存在 \(SG\) 函数值为 \(0\) 的状态,也就是全部为必胜局面,此时 \(x\) 必败。

得到

  • 有向图游戏的某个局面 \(x\) 必胜,当且仅当 \(SG(x)> 0\)
  • 有向图游戏的某个局面 \(x\) 必败,当且仅当 \(SG(x) = 0\)

SG 定理

\(G_1,G_2,\cdots G_m\)\(m\) 个有向图游戏,存在一个有向图游戏 \(G\),其规则是选择其中一个有向图游戏 \(G_i\),在其之上操作一次,无法操作者告负。\(G\) 也成为 \(\{G_i\}\) 的和。

那么 \[ SG(G) = \bigoplus_{i=1}^m SG(G_i) \] \(G\) 先手必胜,当且仅当 \(SG(G) > 0\)

证明。

类似与 Nim 游戏的做法,考虑 \(x = SG(G)\),那么仍然找到 \(SG(G_j)\)\(k\) 为和 \(x\)\(k\) 位都为 \(1\)。此时 \(SG(G_j) \oplus x < SG(G_j)\)。考虑 \(\operatorname{mex}\) 运算的本质,就能发现 \(\big[0,SG(G_j)\big)\) 都能在操作一次 \(G_j\) 后得到,因此一定能通过一次操作使得 \(SG(G_j) \leftarrow SG(G_j) \oplus x\),从而使得 \(SG(G)=0\)

code

随便写一下 Nim 游戏的 \(SG\) 函数做法。

void pre() {
    // sg[i]表示大小为i的石子堆的SG函数值
    rep(i,1,N) {
        SET(s,0);
        rep(j,1,i) s[sg[i-j]]=1;
        rep(j,0,i) if(!s[j]) { sg[i]=j; break; }
    }
}
signed main() {
    pre();
    int ans=0;
    rep(i,1,n) a[i]=read(), ans^=sg[a[i]];
    if(ans>0) puts("win"); else puts("lose");
}

例题

hdu2999

考虑操作一次之后,这段序列就分成了互相独立的两段,可知这一段的一个后继状态的 \(SG\) 函数值等于两小段的异或起来。

所以预处理 \(SG(x)\) 表示长度为 \(x\) 的序列的函数值。处理的过程中枚举所有选那一个长度断开,然后枚举一遍断点即可。

排个序在枚举的时候理论上会快不少。

POJ2311

剪出 \(1 \times 1\) 是必胜局面,不符合「终点为必败局面」的条件。

考虑到剪出 \(1 \times 1\) 必须要 \(1 \times x\) 或者 \(x \times 1\),那么可以把这二者作为终点。

\(SG(x,y)\) 表示长 \(x\)\(y\) 的纸片的函数值。

一刀可以横着或者竖着切,那么对于 \((x,y)\),其后继局面可以是 \((x,i),(x,y-i)\)\((x-i,y),(i,y)\),每一组的 \(SG\) 函数异或值就是 \((x,y)\) 一个后继局面的 \(SG\) 函数值。

枚举 \(i\),可以在 \(O(n^3)\) 的时间里处理出所有 \(SG\) 函数值。

参考

「学习笔记」博弈论 By do_while_true

《算法竞赛进阶指南》 By 李煜东

《算法竞赛》 By 罗勇军,郭卫斌


「博弈论学习笔记」#1 组合游戏基础
https://yozora0908.github.io/2023/notes-gt-1/
作者
yozora0908
发布于
2023年1月28日
许可协议