博弈论练习笔记

一、有向图游戏前置知识

若将局面看成点,将操作看成边,则大部分博弈论题目都可以看成是有向图游戏。

有向图游戏的必胜(N)必败(P)局面的判定引理:

  1. 终局是不能操作的局面
  2. 有向图游戏的除终局外某个局面必胜,当且仅当它的后继局面中存在必败局面。
  3. 有向图游戏的除终局外某个局面必败,当且仅当它的任意后继局面都是必胜局面。

对于有向图游戏的题,能够证明满足上述三条判定引理的做法都是正确的。

一般情况下有向图游戏的终局是定义为必败局面,但也存在一些 anti-SG 游戏的终局是定义为必胜局面。

单个有向图游戏的 SG 函数:

  • SG(x)=mex(SG(y1),SG(y2),,SG(yk)),其中 y1,y2,,ykx 的后继节点。
  • SG(G)=SG(s),其中 G 为整个有向图,s 为有向图的起点。

有向图游戏的和的 SG 函数(SG 定理):

  • SG(G)=SG(G1)xorSG(G2)xorxorSG(Gk),其中 G 为有向图游戏的和,G1,G2,,GkG 的子游戏。

SG 函数的本质是 DAG 上的 DP。

易证 SG 函数是满足判定引理的,因此可以使用 SG 函数来判断必胜必败局面:

  • 当终局为必败局面时,有向图游戏的某个局面必败,当且仅当它的 SG 函数值等于 0
  • 当终局为必胜局面时,有向图游戏的某个局面必败,当且仅当满足下列其中一个条件(SJ 定理):
    • 它的 SG 函数值等于 0 且它的至少一个后继局面的 SG 函数值大于 1
    • 它的 SG 函数值大于 0 且它的任意后继局面的 SG 函数值等于 1

考虑将传统 nim 游戏和 anti-nim 游戏的每堆石子抽象成一个子游戏,在它们的证明过程上稍加补充即可证明。

几点注意事项:

  • 传统 SG 游戏中 mex 可以替换为 01 来表示必胜必败局面,但 multi-SG 游戏中 mex 与 SG 定理密切相关不能替换。
  • 没有规律的有向图游戏一般都暴力记搜求 SG 函数值,时间复杂度为 O(n+m)n 为状态数,m 为转移数(最坏 n2)。
  • 终局必须是不能操作的局面,有的题是到达某个局面后判定胜负,但是还能继续操作,此时必须转化题意。
  • 区分出题面中什么是“后继局面”,什么是“子游戏”,“后继局面”是要 mex,“子游戏”是要 xor

二、nim 游戏

nim 游戏是一种特殊有向图游戏,有许多变形。

有规律的 nim 游戏就找规律,无规律的看成一般有向图游戏暴力记搜即可。

注意 nim 游戏既可以看成是单个有向图游戏(一张 n 堆石子的图),也可以看成是有向图游戏的和(n 张一堆石子的图的和)。

1、传统 nim 游戏

nim 游戏的最初形式。

先手必败当且仅当 a1xora2xorxoran=0(Bouton 定理)。

根据判定引理易证。

模板题。

2、anti-nim 游戏

终局为必胜局面的 nim 游戏。

先手必败当且仅当满足下列其中一个条件:

  • a1xora2xorxoran=0 且存在一个 i 满足 ai>1
  • a1xora2xorxoran>0a1=a2==an=1

思考终局由必败转为必胜时哪些局面的胜负判定会发生改变,根据判定引理易证。

模板题。

3、multi-nim 游戏

在传统 nim 游戏上加入了一种新的操作:将一堆石子分成两堆不为空的石子。

规律是:

sg[x]={x1xmod4=0xxmod4=12x+1xmod4=3

然而我并不会证明……我翻了一堆大佬的博客都说的是打表找出的规律……并且我也没有找到一道例题……

4、Moore's nim-k 游戏

最多从 k 堆石子中取任意石子的 nim 游戏。

先手必败当且仅当将 ai 都写成二进制数,每一位上 1 的个数之和都是 k+1 的倍数。

即二进制数 aik+1 进制 xor 下的 a1xora2xorxoran=0

与传统 nim 游戏的证明过程类似,根据判定引理易证。

略有一点难度的 DP,但是不清楚的题意很容易把人带偏。

第三句话“最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同”很容易让人误解题意……

“最左边”“最右边”“相邻”都是说棋子颜色的排列,与空格无关。

即第 1 个和第 n 个格子可以为空,两个棋子之间可以有空格但颜色也要满足不同。

还需要注意“每当移动某一个棋子时,这个棋子不能跨越两边的棋子,当然也不可以出界”这句话。

它没有说明棋子的移动步数,也就是说在满足上述条件的情况下可以将棋子移动任意步数

理清题意后就能显然发现 Moore's nim-k 游戏的模型了。

由于白色棋子只能向右,黑色棋子只能向左,所以终局必然是 k2 对黑白棋子每一对都怼在一起。

将每对棋子之间的空格数抽象成每堆的石子数,相当于有 k2 堆石子,每次最多从 min(d,k2) 堆石子中取。

正难则反,先手必败时异或和为 0 更容易计算,所以考虑用总方案数 (nk) 减去先手必败的方案数求出答案。

dp[i][j] 表示异或和的第 0i 位全为 0,当前的石子总数为 j 的方案数。

使第 i 位上为 0 必然需要 d+1 的非负整数倍,令其为 l,则需要从 k2 堆石子中拿出 l×2i 个石子。

k2 堆石子中要选出 l 堆石子,使其第 i 位为 1,需要乘上一个组合数 (k2l),因此有:

dp[i][j]+=dp[i1][jl×2i]×(k2l)modp

原问题的每对棋子是有位置的,n 个格子有 k2 个黑棋子和 j 个棋子间的空格,因此白棋子的位置选择为 (nk2jk2)

时间复杂度为 O(nklogn)

由于 i=0 时调用 i1 那一维会越界,我懒直接将数组第一维向右平移一格,即 dp[i][j] 的答案实际存储在 dp[i+1][j] 里。

复制代码
 1 const ll p = 1e9 + 7;
 2 int n, k, kk, d;
 3 ll ans, C[10005][105], dp[15][10005];
 4 
 5 int main()
 6 {
 7     read(n, k, d); kk = k >> 1; d = Min(d, kk);
 8     for (int i = 0; i <= n; ++i) C[i][0] = 1;
 9     for (int i = 1; i <= n; ++i)
10         for (int j = 1; j <= k; ++j)
11             addmod(C[i][j] = C[i - 1][j] + C[i - 1][j - 1], p);
12     int i; dp[0][0] = 1;
13     for (i = 0; 1 << i <= n - k; ++i)
14         for (int j = 0; j <= n - k; ++j)
15             for (int l = 0; l << i <= j && l <= kk; l += d + 1)
16                 addmod(dp[i + 1][j] += dp[i][j - (l << i)] * C[kk][l] % p, p);
17     for (int j = 0; j <= n - k; ++j) addmod(ans += dp[i][j] * C[n - kk - j][kk] % p, p);
18     cout << (C[n][k] - ans + p) % p;
19     return 0;
20 }
AC Code
复制代码

5、阶梯 nim 游戏

每次从第 i 堆中取任意石子移动到第 i1 堆的 nim 游戏,所有石子都到了第 0 堆为终局。

先手必败当且仅当 a1xora3xora5xor=0,即奇数堆的石子数异或和为 0

0 是偶数,奇数堆的石子移动到偶数堆相当于取走了石子,根据判定引理易证。

阶梯 nim 游戏的题灵活多变,思维难度最高,题面一般不会像前几种 nim 游戏一样有明显的提示信息。

考点和难点就在于找到“台阶”“石子”,将题面转化为阶梯 nim 游戏,注意用石子的运动方向确定第 0 级台阶。

棋子只能向左移动,终局必然是所有棋子在最左端,中间没有空格,也就是说要将棋子之间的空格全部排到最右边。

因此定义第 i 个棋子与第 i1 个棋子之间的空格为石子,注意将棋子的位置排序。

棋子向左,空格向右,所以第 1 个棋子之前的空格为第 n 级台阶,第 n 个棋子与第 n1 个棋子之间的空格为第 1 级台阶。

此题虽然可以暴力状压记搜求 SG,时间复杂度 O(m+V2V),但是如果 V 再大一点就不能做了。

与上一道题不同的是,此题的棋子是向右跳跃而非移动一格。

若连续 k 个棋子一段,第 i 个棋子跳到右边,就相当于分成了长度为 i1ki+1 两段,将 ki+1 个棋子同时向右移。

这启发我们将每个空格看成台阶的边界,将连续的棋子看成一堆石子,棋子向右,因此最右边的空格的右边为第 0 级台阶。

时间复杂度 O(m+V)

乍看似乎毫无思路,“每堆石子个数都不少于前一堆的石子个数”暗示了差分,令 c[i]=a[i]a[i1],则 c[i]0

然后就会很神奇地发现,在第 i 堆上取走 k 颗石子相当于 c[i]=k,c[i+1]+=k,这不就是阶梯 nim 游戏的模板吗?

三、特殊有向图游戏

这一部分是除 nim 游戏外其他的特殊有向图游戏。

1、对称博弈

对称博弈的特点是双方都可以通过一定的操作将局面分成无法互相影响且完全相同的两部分,因此:

若先手第一步就能够取胜,则先手必胜,否则后手分成两部分后,无论先手在一部分上做什么操作,后手都可以模仿着在另一部分上做相同的操作,最后先手无法操作,先手必败。

若先手一开始就无法操作,则先手必败,否则先手分成两部分后,无论后手在一部分上做什么操作,先手都可以模仿着在另一部分上做相同的操作,最后后手无法操作,先手必胜。

若先手一开始不能放入圆盘,则先手必败,否则先手可以先放在矩形正中心,之后后手放在哪里,先手就放在其与中心相对称的位置,最后必然是后手无法放,先手必胜。

四、一般有向图游戏

1、传统 SG 游戏

先得到 0 的获胜,即 (a,0) 必败为终局。

以样例 (25,7) 为例:

(25,7) 可以到达 (18,7),(11,7),(7,4)

(18,7) 可以到达 (11,7),(7,4)

(11,7) 可以到达 (7,4)

(7,4) 为必胜局面,则 (11,7) 为必败局面,(25,7),(18,7) 为必胜局面。

(7,4) 为必败局面,则 (25,7),(18,7),(11,7) 都为必胜局面。

因此若 (b,amodb) 为必胜局面,则 ab>1 时为必胜局面,ab=1 时为必败局面。

(b,amodb) 为必败局面,则 (a,b) 为必胜局面。

时间复杂度 O(TlogV)

因为至少有一条 0 边不能走相当于把环断成了链,所以先手从起点出发有两个方向可以选择。

手玩样例会遇到一个问题:将非 0 边变成 0 边断掉后路是否会更劣?

若先手不断后路,则后手继续沿先手方向走必败就一定会断掉这个方向,先手不优还可能更劣;

若后手不断后路,因为先手必断后路所以之前全是 0 边,先手直接往回走就能让后手被夹在 0 边之间,后手必败。

因此先手和后手都一定会断后路,所以胜负只与两个方向的可走的边的数量的奇偶性有关,存在奇数先手必胜,都为偶数先手必败。

定义 sg[x][y][ch] 表示当前先手在点 x,后手在点 y,字符的 ASCII 至少为 ch 时先手必胜还是必败。

状态数为 26n2,转移数为 26nm 即最坏 26n3,时间复杂度为 O(26n3)

注意“k 为自然数”即可以 k=0,取 p0=1 个石子。

打表发现先手必败当且仅当 nmod6=0

1n5 显然先手必胜,n=6 显然先手必败。

n6 的倍数,因为不存在 pk6 的倍数,所以 npk 一定不是 6 的倍数,只能转移到必胜局面,所以先手必败。

n 不是 6 的倍数,则可以取走 15 个石子变成 6 的倍数转移到必败局面,因此先手必胜。

打表发现先手必败当且仅当 nmod4=0

1n3 显然先手必胜,n=4 显然先手必败。

n4 的倍数,因为不存在一个质数 p4 的倍数,所以 np 一定不是 4 的倍数,只能转移到必胜局面,所以先手必败。

n 不是 4 的倍数,则可以取走 13 个石子变成 4 的倍数转移到必败局面,因此先手必胜。

2、multi-SG 游戏

注意题意是出现 1×1 的格纸就判断胜负,但是可能还剩一些能继续剪的格纸,还可以继续操作。

剪出 1×1 的必然是得到了 1×k 的,并且最优策略不可能剪出 1×k 的。

因此删除 1×k 的转移边,定义 1×1 的必败为终局,此时终局就是不能操作的局面了。

一个剪枝是 n×m 的和 m×n 的是一样的,强制让 nm

nm 同阶,时间复杂度为 O(T+n3)

注意区分“后继局面”和“子游戏”,每堆魔法珠是一个子游戏,需要 xor,删除一堆魔法珠是后继局面,需要 mex

V103d(V)32,时间复杂度为 O(n+VV)

五、博弈论思想

这一部分的题目严格意义上讲不属于标准的博弈论题,但是需要用到博弈论思想。

计算机并不是使用最优策略,而是使用非常有趣的搞事情策略。

人选择了一个武将后,计算机一定会拿走默契值最大的武将,但是人可以拿走次大的武将。

由于计算机没有拼成最大和次大的所以必败,人只需要选择每个武将默契值次大的最大值即可。

用 nth_element 可以做到时间复杂度 O(n2)

posted @   jhqqwq  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示