博弈问题
- 动态规划解决博弈问题
- Nim游戏和Sprague–Grundy函数
- 棋子分裂
- Nim-k博弈
- 斐波那契博弈
- 对偶博弈
- 威佐夫博弈
- 两队列取值问题
- 约瑟夫环
- 取反游戏
- Nimber的加法和乘法
- Anti-Nim
- 两端取值问题
- 有向无环图上的博弈
- Nim游戏的一些变种
- 不覆盖子串
- 参考资料
动态规划解决博弈问题
博弈问题是指有两个玩家参与,每个玩家轮流做出决策,最后按照结果判断两个玩家的胜负情况。
如果一个游戏先手必胜,我们称该游戏处于N-position,否则后手必胜,我们称游戏处于P-position。
比如我们可以设计这样一个问题,有一组数,记做a1,a2,…,an,数的总和为奇数。玩家A与B先后轮流决策,每次决策,该名玩家必须从数集中取走最左或最右的数,并从数集中删除。当数取完时,取得的数总和较大的胜利。问两个玩家都做最优决策时,哪个玩家会胜利。
这个问题,就是一个经典的博弈问题,我们可以用动态规划枚举所有可能的状态解决。记dp(l,r)表示当数集为al,al+1,…,ar时,如果游戏是N-position,记为1,否则为P-position,记为0,可以很容易推出公式:dp(l,r)=max(1−dp(l+1,r),1−dp(l,r−1))。
通过上面的动态规划我们就能以O(n2)的时间复杂度解决博弈问题。如果我们将每个dp值视作一个结点,并从dp(l+1,r)和dp(l,r−1)中向dp(l,r)连接一条单向边,就可以构造一幅有向无环图。这幅图,可以清晰展示整个决策流程。
实际上,上面这个博弈问题,有非常简单的解决方案,那就是先手必胜,因为先手可以决定自己选择奇下标的数还是偶下标的数,因此必胜。可以看出虽然动态规划很强大,但是如果能直接给出有用的性质,可以大幅优化时间复杂度。
决策不一定是非胜即负的,比如考虑井字游戏,A持白子,B持黑子,每次可以在一个3*3表格中的一个空白格子中落子,如果三个白子连成一条直线,则A胜利,游戏结束,如果三个黑子连成一条直线,则B胜利。
很显然,如果双方都最优决策,那么游戏一定是平局的。在上面的这幅图中,这意味着有一部分结点代表着平局,平局的结点仅有向平局和胜利结点的边。
决策图不一定是无环的,比如这样一个游戏。如果A和B各持有两个整数,整数大小为0~9。二人轮流出牌,当A出牌时,将其中一张牌x换成(x+y),其中y是上次B出的牌(默认A和B之前出的牌为0),对于B同理,只是y是A上次出的牌。当两个玩家手中持有的牌有一张换成0时,就认为该名玩家获得胜利。
很显然还是能通过状态压缩后建立图来解决。但是图中存在环,因此我们需要利用Bellman-Ford算法的松弛技术来完成。而一个结点如果在松弛完后,状态还是无法确定,那么这个结点一定代表平局。
Nim游戏和Sprague–Grundy函数
用动态规划解决博弈问题,很容易遇到瓶颈,比如状态数过多,无法逐一计算。
考虑Nim游戏,有n堆石头,第i堆石头有ai个石头。玩家A、B轮流出手,每次出手,玩家必须选择一堆石头,并从中取走至少一个(最多可以全取)。如果无法完成操作,则认为玩家失败。
很显然,我们可以用动态规划,共∏ni=1ai种状态,如果有100堆石头,每堆有100个石头,那么状态数将达到100100,这显然是无法完成的。
这时候估计大家现在开始纷纷开脑洞,猜测每堆奇偶性会影响胜负等等。
下面说一下正确的解题姿势。
我们之前定义的动态规划函数的值仅为1和0,实际上我们抛弃了很多有用的信息,现在我们把它们加回来。首先所有堆石子为0的结点值为0,保持不变。但是对于其它结点u,我们记所有从它出发沿单向边移动一步可以抵达的结点集合为v1,v2,…,vm,记sg(u)=mex(sg(v1),sg(v2),…,sg(vm))。其中sg为Sprague–Grundy函数。而mex函数值为不同于所有参数的最小非负整数,比如mex(1,2)=0,mex(0,2)=1。
我们这里提到的Nim游戏,现在可以转换为另外一个问题,我们将每一堆都视作图中的一个棋子,每位玩家都可以选择任意一个棋子沿着有向边移动一步,如果所有棋子都无法移动,那么该名玩家失败。
下面我们讨论两个命题。
命题1:如果仅一枚棋子,那么游戏处于P-position当且仅当该棋子所在结点的sg值为0
证明:对于代表失败结果的结点,该棋子没有外向边,sg值显然为0。对于sg值为0的棋子,其所有相连的结点sg值肯定非0,因此其只能移动到N-position,即该结点必定为P-position。而对于sg值非0的棋子,其一定与某个sg值为0的结点相连,因此移动到该结点,游戏进入P-position,因此该结点对应的是N-position。这里证明不是非常严谨,可以换成归纳法进行证明。
命题2:如果有n个独立棋子,那么游戏处于P-position当且仅当所有棋子所在的sg值的异或和为0
证明:如果所有棋子都处在代表失败结果的结点,那么它们的sg值异或和自然是0。如果异或和为0,那么移动一枚棋子,记其原来的sg值为a,后来的sg值为b,必定有a≠b,故此时异或和一定为a⊕b≠0,因此N-position之后一定是P-position。而如果异或和s不为0,那么我们一定能找到一个棋子,其所处结点的sg值为x,满足x包含s中二进制的最高位,我们将该棋子从所在结点移动到sg值为s⊕x<x的后继结点上,这时候异或和为s⊕x⊕x⊕x=0,因此我们在N-position后一定能移动到P-position。配合归纳法可以证明。
这样我们就可以将从n堆石头中移除石头看做为n个独立游戏,而我们只要建立n堆石头各自的决策图,并计算棋子所在结点的sg值的异或和就可以判断游戏的状态了。但是由于Nim游戏中每个独立游戏拥有相同的决策图,因此我们可以复用,事实上,这里我们连决策图都不用建立,剩余n个石子对应的结点的sg值一定是n。
我们考虑到我们仅仅利用了决策图的sg值,与决策图具体代表的游戏是无关的。因此我们可以同时玩多个游戏,只需要利用sg函数就可以快速计算游戏所处的状态。比如我们将Nim游戏稍加变形,操作第i堆石头一次性必须移除1~i个石头。我们可以将每一堆石头建立独立的决策图,并计算每个结点的sg值。之后异或所有决策图上棋子的sg值,为0,则游戏处于P-position,否则处于N-position。
棋子分裂
我们稍微修改一下游戏。我们每次并不能移动棋子,但是可以选择一枚棋子,将其分裂为若干颗新的棋子,每个棋子落在特殊的结点上,保证若干步后游戏一定会结束。
这时候我们可以修改每个结点的sg值。在结点u上,假设有k种分裂策略,第i种分裂策略分裂后棋子分别落在v1i,v2i,…。那么我们定义sg(u)=mex(v11⊕v21⊕…,…,v1k⊕v2k⊕…)。
稍微修改命题2的证明可以很容易证明游戏处于P-position当且仅当所有棋子所在sg值的异或和为0。
Nim-k博弈
Nim游戏是Nim-k游戏的一个子集。Nim-k游戏定义为,有n堆石头,每堆分别有a1,a2,…,an个石头,两个玩家A、B轮流执行下面操作:
选择1~k个堆,并从这k个堆中各移除若干个石头(不同的堆允许移除不同数量的石子,至少一个)。
如果一个玩家不能执行操作,则认为失败。A先手,B后手,问谁胜利。
对于我们之前的讨论的Nim游戏可以认为是Nim-k中k为1时的特殊情况。之前已经证明过了Nim游戏处于P-position当且仅当每堆石头石子数的异或和为0。这里我们直接给出Nim-k游戏的胜利条件,Nim-k游戏处于P-position当且仅当对于所有i,One(i)为k+1的倍数,其中One(i)表示a1,a2,…,an中二进制第i位为1的数值个数。
很显然对于失败态,此时所有One(i)均为0,因此处于P-position。
对于某个P-position,对于任意一次操作后,我们记j为本次操作修改的最高比特位。由于是最高位,因此第j位的修改一定是1→0。1→0转移至少发生1次,最多发生k次,而由于初始时One(j)=0(modk+1),因此修改后One′(j)一定不能整除k+1。即P-position转移后一定是N-position。
对于某个N-position,我们可以构造一种取法,使得下一个状态为P-position。我们维护一个集合(初始时为空),并不断向其中加入石堆。
- 找到一个最大的值j,使得r=One(j)(modm+1)≠0。如果不存在则算法终止,否则进入第2步。
- 设集合中石头堆中第j位为1的有a个,为0的有b个。那么如果r≤a,我们从中选择r个石头堆将第j比特从1改为0,之后回到第1步。否则进入第3步。
- 如果r+b≥(m+1),则我们从中选择m+1−r个堆,将第j比特从0改为1,之后回到第1步。否则进入第4步。
- 我们取r−a个第j比特位1的石头堆加入集合,并将r个石头堆将第j比特从1改为0。这样我们就将第j比特修正为k+1的倍数。此时集合的大小为r−a+a+b=r+b<m+1,因此是合法的。$=
Nim-k游戏虽然类似于Nim游戏,但是不能保证对于一般的决策图也能满足这样的性质。即允许同时操作1~k个棋子在决策图上移动一步,不能保证每个对于每个比特i,One(i)均为0就能保证是P-position。考虑这样一个游戏,共4堆石头,数量为1,1,1,2,每次允许选择1~2个石头堆,并移除一个石子。这样4个石头堆对应的SG函数分别为1,1,1,0。因此满足One(0)=3能整除2+1,因此我们有理由认为这是一个P-position,但是实际上这是一个N-position,因为我们可以将局势改变为0,1,1,1。
斐波那契博弈
有n个石头,A、B轮流出手,每次至少拿一个石头,最多拿对手上一次取的数目的两倍。第一次取的人不能全取。问先手胜还是后手。
直接给答案,如果n是斐波那契数的一项,则游戏是P-position,否则是N-position。
先说点斐波那契数列的性质。
性质1:32Fi<Fi+1<2Fi
性质2:Fi+2≥2Fi
性质3:任意正整数都可以表示为若干个不连续的斐波那契数列项的和
对于0,0是斐波那契数列的第0项,因此是P-position。
下面我们通过归纳法证明,假设对于小于n的斐波那契项都是P-position。如果n是斐波那契数列的一项,我们可以得出n是前两项a、b的和,即a+b=n。则我们选择的一定小于a,否则对手会一次性将剩余的一起取走。由于归纳法,我们得知在经过若干轮交手后,B完成一次操作,使得取走的石子总数为a,留下的石子数为b。考虑B最后一次取的数量,至少为1,最多为23a。这样A之后最多取43a<b,即相当于我们在b上玩游戏,且A先手取,不能完全取尽。由归纳法知最后能取尽b的一定是B。因此B一定胜利,游戏处于P-position。
如果n不是斐波那契的任意项,我们可以将其展开为f1,f2,…,fk,满足两两不连续,且f1<f2<…,fk。A第一次取f1个石子,而之后变成b不能先手取,之后我们能保证A能取到第f1,f1+f2,…,n个石子。
对偶博弈
n个石子,围成一个环。A、B轮流出手,每次可以取连续的一段石子,长度为1~k。不能完成操作的认为失败,问谁胜利。
当k为1的时候,每个玩家每次只能取走一个石子,因此游戏的胜负仅于n的奇偶性有关。
当k大于1时,若n≤k,则A一次性能取完,A胜利。
当k大于1且n>k时,无论A第一次怎么取,设剩下m个连续石子,B可以通过一次操作,将石子分成两个等长连续段。之后无论A在哪个部分操作,B在另外部分同步操作,就能保证取走最后一个石子,获得胜利。
威佐夫博弈
有两堆石子,分别有n、m个石子。A、B轮流出手,每次可以从一堆取任意石头,或从两堆石子中取相同数量石头。问谁胜利。
不妨设n≤m,游戏处于N-position当且仅当,存在一个k,使得n=⌊Wk⌋且m=⌊(W+1)k⌋,其中W=1+√52。
记L(i)=⌊Wi⌋,记R(i)=⌊(W+1)i⌋,有L(N)∩R(N)=∅和L(N)∪R(N)=N。
两队列取值问题
有两个队列,每个队列包含一个非负值序列。给定一个阈值m(m不超过两个队列中所有元素之和),我们维护一个值sum,表示已经从两个队列中取出的数值的总和。
现在有两个人A、B。他们每次需要执行下面一个操作:
从两个队列中任选一个非空队列,从队列中弹出头部数值。
如果某个人完成一次操作后,sum值达到m,那么就判定他输,另外一个人赢。
这个问题的解法非常有趣。设队列1的长度为W,队列2的长度H,我们可以绘制一个H+1行W+1列的网格。第i行j列表示队列1已经弹出i个元素,队列2弹出j个元素,接下来操作的人是否会获胜。如果能获胜,我们将网格涂上白色,否则涂上黑色。同理对于无效网格(即执行完这些操作sum已经超出阈值),我们默认它们都是白色。
我们需要证明一些非常有用的命题:
命题1:任意两个黑色网格不会相邻
命题2:如果网格(a,b)是白色的,那么(a+1,b+1)也是白色网格。
证明:
如果(a+1,b+1)是无效网格,命题显然,之后仅考虑(a+1,b+1)是有效网格的情况。证明非常简单,如果网格(a+1,b+1)是有效网格,那么(a,b+1)和(a+1,b)一定也是有效网格。由(a,b)是白色可以推出(a,b+1)和(a+1,b)至少有一个是黑色网格,同理可以推出(a+1,b+1)一定是白色网格。
命题3:如果网格(a+1,b+1)是黑色的,那么(a,b)也是黑色的
证明:
由于(a+1,b+1)是黑色的,因此(a+1,b)和(a,b+1)都一定是白色的,由此可以得知(a,b)是黑色的。
命题4:如果(a+1,b+1)是有效网格,那么网格(a,b)和网格(a+1,b+1)一定同色,
证明:
根据命题2和命题3,我们只需要考虑不存在(a,b)是黑色的,而(a+1,b+1)是白色的情况。
考虑到(a,b)是黑色的,因此(a,b+1),(a+1,b)一定都是白色的有效网格。而考虑到(a+1,b+1)也是白色的,因此(a,b+2),(a+2,b)则一定是黑色的网格。
而由于(a+1,b+1)是白色的有效网格,因此(a+2,b+1),(a+1,b+2)至少一个是黑色网格。而再考虑到(a,b+2),(a+2,b)一定是黑色的网格,这与命题1相悖。因此命题得证。
因此我们希望得知网格(0,0)的颜色,只需要去查询(1,1)的颜色。因此我们实际上需要计算点 (0,0),(1,1),…,(min{H,W},min{H,W}) 的颜色。总的时间复杂度为 O(min{H,W})
提供一道问题。
约瑟夫环
约瑟夫环的问题如下:
有n个人围成一圈,我们顺时针将人标记为0,1,…,n-1。从标记为0的人开始沿着顺时针报号(1,2,3等),谁报到k,就会被杀死。之后从被杀死的人后一个人继续重新开始报号。
在这样的一个游戏中,有若干个问题非常有趣:
问题1:第i个死亡的人是谁。
问题2:编号为j的人是第几个死亡的。
先考虑问题1,可以很容易推出一个递推算法,记f(n,i)表示剩余n个人的时候,第i个死亡的是谁。g(n,j)表示在只剩下n个人的时候,第j个人在第几个回合死去。
得出下面递推公式:
f(n,i)=(f(n−1,i−1)+k)%ng(n,j)=g(n−1,(j−k)%n)+1利用这些递推公式,我们可以在O(n)的时间复杂度内回答以上问题。
但是可以发现f(n−1,i−1)+k大部分时候都会不超过n,因此我们可以直接多步合并执行来优化函数f,同理j−k大部分时候也都不会小于0,因此可以同样进行优化。
优化后两个函数的时间复杂度应该为O(min(n,klnnk))。
取反游戏
考虑有这样一个序列a1,a2,…,an,A和B两个人用这个序列玩一个游戏,A先手,游戏步骤为:
取一个数值i,要求ai>0,之后将ai减去1,并且可以选择i后面的任意多个有效下标I=i+1,i+2,…,I可以为空集,对于任意j∈I,将aj加上1。一旦有人不能再操作,那么这个人就输去比赛,问先手胜还是后手胜。
很容易发现这个问题和奇偶性有关,我们可以将问题重新描述为:
取一个下标i,要求ai为奇数,选择任意多个有效下标I=i,i+1,i+2,…,对于任意j∈I,改变aj的奇偶性。一旦有人面对全是偶数的情况,那么这个人就输去比赛,问先手胜还是后手胜。
由于奇偶性问题和数值大小是没有任何关系的,因此我们可以认为ai都足够大,大到能支撑到游戏分出胜负为止。
这个问题还是很难解决,我们可以建立一个新的序列bi,用于描述ai,如果ai与ai−1的奇偶性不同,那么bi为1,否则bi为0。这样之前的问题中的区间[l,r)的翻转操作,可以用序列bi中位于l处的1移动到r处来描述。
取一个下标i,要求bi为1,选择某个下标j,满足i<j≤n,将位于i处的1移动j+1处。一旦面临b1,…,bn都是0的情况,那么这个人就输去比赛,问先手胜还是后手胜。
考虑位于i处的1,移动1,相当于取石子游戏,它的SG函数值应该为n+1−i。而序列bi中的多个1,可以理解为多个独立的NIM游戏。
这边的证明是依赖于直觉的,暂时没有想到严谨的证明。
Nimber的加法和乘法
定义mex(S)表示min(N/S),即S中未出现的最小的自然数。其中mex的意思是minimum excludant。
Nimber的加法定义为:
a⊕b=mex({a′⊕b:a′<a}∪{a⊕b′:b′<b})其值与a和b二进制的亦或和相同。
Nimber的乘法运算定义为:
a⊗b=mex({(a′⊗b)⊕(a⊗b′)⊕(a′⊗b′):a′<a,b′<b})可以Nimber的加法运算符合封闭性,满足结合律和交换律,且加法单位元为0,每个数的逆元为自身,因此Nimber构成了一个加法群。
可以发现:
- a⊗0=0
- a⊗b=b⊗a
- a⊗1=a
- (a⊗b)⊗c=a⊗(b⊗c)
- (a⊕b)⊗c=(a⊗c)⊕(b⊗c)
即乘法运算也满足结合性,分配律,交换律等,存在单位元1,故Nimber构成了一个交换环。
要计算Nimber乘积,我们需要一些更加强力的性质:
对于任意x,y<22a
- x⊗22a=x⋅22a
- x⊗y<22a
- 22a⊗22a=3222a
利用这些性质我们可以设计一个递归算法,O(log2alog2b)求解a⊗b。具体可以参照参考资料中《从“k倍动态减法游戏”出发探究一类组合游戏问题》这篇文章。
SG定理:设若干个棋子的SG函数值为SG(x1),…,SG(xn),则这些棋子共同的SG值为SG(x1)⊕…⊕SG(xn)。
Tartan定理:记若干个游戏G1,…,Gn的积为G(V,E)=G1⋅…⋅Gn,其中V=V1×…×VN(笛卡尔积),E=(x,y)|(xi,yi)∈Ei,其中x=(x1,…,xn),y=(y1,…,yn)。那么棋子x=(x1,…,xn)的SG值为SG(x1)⊗…⊗SG(xn)
我们可以这样理解。
- 如果有一个游戏,无法操作的时候玩家失败。则我们知道游戏的SG函数值决定了先手还是后手必胜,如果SG函数值为0,则先手必败,否则先手必胜。
- 如果同时有n个游戏在进行,博弈双方每次只能选择一个游戏操作,只有当所有游戏都不能操作的时候玩家才失败,则游戏的SG函数值可以通过各个单独的函数的SG值的Nimber和得到。
- 如果同时有n个游戏在进行,博弈双方每次需要同时选择所有游戏操作,只有不能操作的玩家才失败,则游戏的SG函数值可以通过各个单独的函数的SG值的Nimber积得到。
问题1:我们有一个n×m矩阵A,每个网格中都有一盏灯,灯或开或关。现在要求两人进行博弈,轮流操作,每次操作都需要选择一个矩形(长宽均至少为2),且矩阵的右下角的灯必须为开状态,操作完成后,矩阵的四角的灯的状态发生改变(由开变关或由关变开)。无法操作的人视作失败。问先手还是后手必胜。一开始总共有k盏灯开着,告诉你它的坐标。这里1≤n,m≤1018,0≤k≤105。
发现单一维度下就是一个普通的NIM游戏,因此我们将行游戏和列游戏计算笛卡尔积就可以得出这个游戏。故SG(x,y)=x⊗y。
这里顺带一提,允许退化的情况(即高度和宽度允许为1),这时候我们在左边和上边额外加一列一行,行号和列号均为0,且这一行一列的SG函数值均为0即可。这时候比如对于高度退化的情况下,我们可以认为矩阵的上部正好匹配了最顶上的那一行。于是乎我们吧原先的行列编号全部加1,就可以复用解法了。
问题2:有n个堆,第i个堆有ai个石头,两人轮流操作,每次操作需要选择一个堆,拿走至少1个,最多m个石头,求先手还是后手必胜。这里1≤ai≤109,1≤n≤105,1≤m≤103。
由于不同堆的规则是相同的,因此我们可以只处理一次SG函数。同时可以发现SG的函数应该满足SG(x)=SG(x+m+1)(周期性)。因此我们可以只需要算出SG(i),其中i≤m。
问题3:有一行灯(第一个灯的编号为0),每个灯的状态为0,1,对应关灯和开灯状态。之后每次你可以选择某个非空子序列,要求前缀最靠右的灯一定处于开状态。要求将整个子序列中的灯的状态进行转换。现在两人轮流进行操作,不能操作的人为输家。问先手还是后手必胜。
这个游戏是Ruler游戏。第i盏灯的SG函数值为SG(i)=lowbit(i+1),即i二进制形式中的最低一位1。具体证明不会。
问题4:有一行灯(第一个灯的编号为0),每个灯的状态为0,1,对应关灯和开灯状态。之后每次你可以选择长度不超过k的子序列,要求子序列z最靠右的的灯一定处于开状态。要求将整个子序列中的灯的状态进行转换。现在两人轮流进行操作,不能操作的人为输家。问先手还是后手必胜。
这道题,与问题3有点类似,只是为3没有长度约束。打表可以发现,对于k,其约束与highbit(k)是相同的(从k减少到highbit(k)不会影响最终的胜负)。同时会发现SG函数的周期正好为highbit(k)的因数,而前highbit(k)个灯的SG函数与没有约束的情况下是相同的,即普通的Ruler博弈。
利用取模,我们对于位于x的灯,我们可以推出SG(x)=lowbit((x(modhighbit(k))+1))。
问题5:我们有一个n×m矩阵A,每个网格中都有一盏灯,灯或开或关。现在要求两人进行博弈,轮流操作,每次操作都需要选择一个矩形(长宽均至少为2,宽度不能超过W,高度不能超过H),且矩阵的右下角的灯必须为开状态,操作完成后,矩阵的四角的灯的状态发生改变(由开变关或由关变开)。无法操作的人视作失败。问先手还是后手必胜。一开始总共有k盏灯开着,告诉你它的坐标。这里1≤n,m≤1018,0≤k≤105。
可以发现行游戏和列游戏都是问题4,我们可以将其进行笛卡尔积得到问题5。而合并后的游戏可以用Nimber积求解。
提供一道题目:SRM748 Rectoggle。
Anti-Nim
Anti-Nim的问题描述和Nim游戏基本相同,除了拿走最后一个石子的人认为是输家。
命题:给定n个游戏,双方轮流操作,每次操作可以操作一个游戏。当所有游戏的SG函数值均为0的时候认为最后一次操作的人失败。那么先手仅在3种情况下必胜:
- 每个游戏的SG函数值均为0,1,且这些游戏的SG函数值亦或和为0。
- 存在正好一个游戏的SG函数值大于1。
- 存在多于一个游戏的SG函数值大于1,且这些游戏的SG函数值亦或和大于0。
证明:
首先我们可以忽略状态为0的单个游戏,因为如果一方将其变成非0,那么另外一方可以将其重新变回0。同样我们也不考虑SG函数值从1变到更大的情况,因为一方将其变大,另一方一定可以将其还原。
第一个条件如果成立,那么必胜是很显然的,因此不讨论。
当第二个条件成立的时候,如果有偶数个游戏的SG函数值为1,则我们将那么SG函数值大于1的游戏转换为1,否则转换为0,因此这样就进入了第一个条件下先手必败的状态。
现在仅考虑存在多于一个游戏的SG函数值大于1的情况。如果SG函数值为非0,先手可以将其转换为0,而后手只能将其转换为非0。同时可以发现后手操作时,面对的都是所有游戏SG函数值的亦或和为0的情况,因此此时至少有两个游戏的SG函数值大于1,不可能进入条件2逃离。
两端取值问题
题目1:给定一个长度为n的序列a1,…,an。之后两人轮流操作,每个人在自己的回合可以从队列头部或尾部弹出一个数值(弹出后这个数值就从队列中删除)。如果序列为空则游戏结束。在游戏结束后,如果一方弹出的数的总和比另外一方大,则获得胜利。保证a1+…+an是奇数(即不会出现平局)。问先手必胜还是后手必胜。其中2≤n≤105,且n是偶数。
先手必胜,因为先手可以决定自己拿走所有奇数下标的数还是偶数下标的数。
题目2:给定一个长度为n的序列a1,…,an。之后两人轮流操作,每个人在自己的回合可以从队列头部或尾部弹出一个数值(弹出后这个数值就从队列中删除)。如果序列只剩下一个元素时游戏结束。先手方希望让剩下的元素尽可能大,而后手方希望让剩下的元素尽可能小,两者都是最优决策。问最后剩下的数为多大。其中1≤n≤106。
考虑先手面对偶数的情况。可以发现先手一定可以取到max(xn/2,xn/2+1),因此这是结果的一个下界。而后手只要做与先手相反的操作(先手弹出头部,则后手弹出尾部),就可以保证最终剩下的数是xn/2,xn/2+1中的一个(这显然对于后手是最优的,即最终值正好等于下界)。因此这时候结果一定是max(xn/2,xn/2+1)。
可以发现对于后手面的偶数的情况下,最终结果为min(xn/2,xn/2+1),证明方式类似。
再考虑先手面对奇数的情况。我们知道如果我们选择弹出头部,则最终结果为min(x(n+1)/2,x(n+1)/2+1),对应的如果我们选择弹出尾部,则结果为min(x(n−1)/2,x(n−1)/2+1)。而由于先手希望结果尽可能大,因此答案为max(min(x(n+1)/2,x(n+1)/2+1),min(x(n−1)/2,x(n−1)/2+1))。
一道题目。
有向无环图上的博弈
有向无环图上的博弈,可以发现出现的最大sg函数值是min(V,√E)。
题目1:给定一个n个顶点m条边的有向无环图。之后不断重复以下操作:随机生成一个1到n+1的随机整数v,如果这个v不超过n,则在顶点v上加入一个棋子。如果v=n+1,则结束操作,进入比赛。比赛流程非常简单,两人轮流操作,每次沿着一条有向边移动一枚棋子。谁不能移动了就算失败。问先手获胜的概率是多少。其中1≤n,m≤105
提供一道题目。
预先算出所有顶点的sg函数值。可以发现值的范围是√E之内。之后建立期望矩阵,xi表示比赛开始前游戏的sg函数为i的期望次数,只后高斯消元即可,时间复杂度为O(E1.5)。
Nim游戏的一些变种
考虑有多个Nim游戏。两个玩家A、B轮流操作,A先手。操作的人会选择其中一个未结束(可以继续操作)的Nim游戏,并做一些操作,使游戏的状态变更。
一般的情况下,如果某个玩家面对的所有游戏都结束的时候,那么他就是输家。我们可以通过为每个Nim游戏的结束态的sg函数设置为0,并将所有Nim游戏的sg函数值异或起来。如果异或和为0,那么先手必败,否则先手必胜。
现在我们稍微修改一下分出胜负的条件。
- 如果任意一个Nim游戏结束的时候,最后操作的人为赢家。
- 如果任意一个Nim游戏结束的时候,最后操作的人为输家。
当然我们必须保证所有Nim游戏初始的时候不处于结束状态。
现在我们需要判断是A获胜还是B获胜。
我们考虑任意一个游戏,我们加入新的状态:预备态。对于条件1的情况下,一个状态是必败态,当且仅当这个状态可以通过一步将游戏结束;而对于条件2,只有游戏结束的状态才是必败态。必败态的含义是在这个状态上进行操作的玩家会获胜。
可以发现无论在哪种情况下,当前操作的玩家一定不会允许游戏进入必败态。换言之,所有会导致游戏切换到必败态的操作都是被禁止的。可以发现此时如果一个状态,它只能转移到必败态,那么它的sg函数值为0,否则它的sg函数值为所有可进入状态的sg函数值的mex值。
之后对于对个游戏存在的情况,我们可以将这些游戏的sg值异或起来,记结果为x。A获胜的条件是:至少一个游戏为必败态或者x≠0。
不覆盖子串
考虑这样一个问题,有长度为n的一个01序列。现在由A和B轮流操作。操作人每次选择一段连续的仅包含0的非空子串删除,当无法操作时,当前操作人为输家。
现在要求判断先手必胜还是必败。
我们实际上可以把每段连续的0看成一个单独的游戏,每次我们删除子串,对应的就是将一个游戏分裂为两个子游戏(可能存在空游戏)。
我们可以发现每个单独游戏的状态仅由串长度所决定,对于长度为k的串,记它的sg值为sg(k)。
下面我们证明sg(k)=k。当k=0的时候,显然。现在可以发现状态(k)可以转移为(0),(1),…,(k−1),因此sg(k)≥k。接下来我们考虑(k)分裂为两个子游戏的情况(a),(b)的情况,此时有a+b<k。由于sg(a)=a且sg(b)=b,因此sg(a)⊕sg(b)≤a+b<k,故我们有sg(k)=k。
提供一些题目: