前置芝士
如果不明白 N i m Nim Nim 游戏是啥的话,下面的内容不保证能看懂qwq。
SG函数
意义
这个函数的参数是游戏的状态,并且返回值是一个非负整数,当函数值为 0 0 0 时,先手必败,否则先手必胜。
mex运算
这是一个施加于集合的运算,表示求出这个集合中最小的没有出现过的非负整数,比如 m e x { 0 , 2 , 3 } = 1 , m e x { 1 , 2 } = 0 , m e x { } = 0 mex\{0,2,3\}=1,mex\{1,2\}=0,mex\{\}=0 mex{0,2,3}=1,mex{1,2}=0,mex{}=0。
SG函数的求法
设当前游戏的状态为 x x x,后继状态(也就是操作一次后能得到的状态)有 a 1 , a 2 , . . . , a p a_1,a_2,...,a_p a1,a2,...,ap,那么 S G [ x ] = m e x { S G [ a 1 ] , S G [ a 2 ] , . . . , S G [ a p ] } SG[x]=mex\{SG[a_1],SG[a_2],...,SG[a_p]\} SG[x]=mex{SG[a1],SG[a2],...,SG[ap]}。
举个栗子
现在你有 n n n 个石子,每次可以取走 a ( a ∈ { 1 , 3 , 4 } ) a(a\in\{1,3,4\}) a(a∈{1,3,4}) 个,两个人轮流取,谁取完了谁就获胜,问先手是否必胜。
看起来奇奇怪怪的问题,用 S G SG SG 函数可以轻松解决。
首先, 0 0 0 个石子时肯定是必败态,所以 S G [ 0 ] = 0 SG[0]=0 SG[0]=0。
然后根据 S G SG SG 函数的求法一步步推即可:
有 1 1 1 个石子时,后继状态只有 0 0 0,所以 S G [ 1 ] = m e x { S G [ 0 ] } = 1 SG[1]=mex\{SG[0]\}=1 SG[1]=mex{SG[0]}=1。
有 2 2 2 个石子时,后继状态只有 1 1 1,所以 S G [ 2 ] = m e x { S G [ 1 ] } = 0 SG[2]=mex\{SG[1]\}=0 SG[2]=mex{SG[1]}=0。
有 3 3 3 个石子时,可以取 1 1 1 个或 3 3 3 个石子,后继状态有 0 , 2 0,2 0,2,所以 S G [ 3 ] = m e x { S G [ 0 ] , S G [ 2 ] } = 1 SG[3]=mex\{SG[0],SG[2]\}=1 SG[3]=mex{SG[0],SG[2]}=1。
……
推完之后,看回意义,完全满足当函数值为0时,先手必败,否则先手必胜
。
为什么呢?
仔细回忆必胜态和必败态之间转移:当一个状态的后继状态全都是必胜态时,这个状态就是必败态,如果后继状态至少有一个必败态,那么这个状态就是必胜态。
在 S G SG SG 函数中这也得到了很好的体现:当一个状态的后继状态的 S G SG SG 函数值中至少有一个 0 0 0 时,这个状态的 S G SG SG 函数值肯定不为 0 0 0,如果没有 0 0 0,那么这个状态的 S G SG SG 函数值肯定为 0 0 0。
别忘了, 0 0 0 代表必败态。
SG定理
你可能会问了,那么这些问题不是只需要一个bool数组来记录必胜或必败就可以了吗,为什么需要 S G SG SG 函数这么麻烦呢?
这时,我们就要请出 S G SG SG 定理了:
一个游戏的 S G SG SG 函数值等于各个游戏的 S G SG SG 函数值的 N i m Nim Nim 和
其中,各个游戏
指的是那个大的游戏中的子游戏,而
N
i
m
Nim
Nim 和,其实也就是异或和。
譬如就说 N i m Nim Nim 游戏吧,每堆石子就是一个子游戏,求出每堆石子的 S G SG SG 函数值,异或起来就得到了整个游戏的 S G SG SG 函数值。
证明
证明不难,想想就能明白。
要知道,一个 S G SG SG 值为 k k k 的状态,必然能转移到 S G SG SG 值为 j ( 0 < j < k ) j~(0<j<k) j (0<j<k) 的状态,那么这样一想,不就相当于一个有 k k k 个石子的堆给你拿走了 k − j k-j k−j 个嘛,这样将 S G SG SG 值转化为了石子数来考虑,所以我们可以将 S G SG SG 值异或起来,本质就是 N i m Nim Nim 游戏。
但是可能有人会问,一个 S G SG SG 值为 k k k 的状态,也可能转移到一个 S G SG SG 值为 t ( t > k ) t~(t>k) t (t>k) 的状态啊?
虽然这个操作有点像在放石子
,但事实上,并不能做到无限放石子
,也就是说,保持了后继状态有限
这一前提,所以不用担心,还是能够异或求解的。毕竟异或求解的本质操作,就是在异或和不为
0
0
0 时在相应位置取走若干个石子使得异或和为
0
0
0,就算多了个“放石子”操作,也不会影响拿石子这一操作,能拿的,依然还能拿。