博弈论SG函数

参考:
http://www.cnblogs.com/ECJTUACM-873284962/p/6398385.html
http://www.cnblogs.com/ECJTUACM-873284962/p/6921829.html

巴什博奕

只有一堆石子,每个人可以从里面取1~m个石子,先取光者胜。

n = m + 1 n = m+1 n=m+1先手必败,因为先手无论选什么,都会使其个数小于m。

因此可以推出更一般的情况:
n = k ∗ ( m + 1 ) n = k*(m+1) n=k(m+1)先手必败,因为后手总能构造出 n = t ∗ ( m + 1 )   t < k n = t*(m+1) \ t < k n=t(m+1) t<k的情况。

总结: 只要能构造出两个可以相互转换的状态便可得出答案。(必胜态,必败态)。

尼姆博弈

有n推石子,每堆有$m_i$个石子,每次可以取在一堆中取任意个石子。

学着巴什博奕做,构造两个可以相互转换的状态。

把每堆石子的总个数用二进制的形式相加。每位都不进位。
例如:
1 2 3
001
010
011

= 022

因为每次都只能在一堆石子上操作,所以对于每一位,每次只能减1或者不变。可以观察出,当所有位都为偶数的时候(偶状态),先手必败,当有一位为奇数(奇状态)的时候先手必胜。

因为总能从一个奇状态转变为一个偶状态。反之,也能从一个偶状态转变为奇状态。 但无法保持当前状态不变。

考虑异或,当一位出现偶数个时,其贡献为0,否则为1。
所以可以将每一堆的个数都异或起来,如果异或和!=0,则先手胜,否则先手败。

有n推石子,每堆石子的个数分别为1,2,3,4,....,n,每次可以取在一堆中取任意个石子。n特别大。

因为n特别的大,所以没法直接对其异或。 但是连续正整数的异或是有规律的。
f[l,r]: [ l , r ] [l,r] [l,r]的异或和
推论1: f [ 0 , 2 k − 1 ] = 0 , 2 ≤ k f[0,2^k-1]=0, 2 \leq k f[0,2k1]=0,2k
XJB证明: 二进制的每一位上都有 2 k − 1 2^{k-1} 2k1个1。

f [ 0 , n ] f[0,n] f[0,n]

  1. n为奇数
    f [ 0 , n ] = f [ 0 , 2 t − 1 ] ⊕ f [ 2 t , n ] = f [ 2 t , n ] f[0,n] = f[0,2^{t}-1] \oplus f[2^t,n] =f[2^t,n] f[0,n]=f[0,2t1]f[2t,n]=f[2t,n]
    这个区间有 m = n − 2 t + 1 m = n-2^t+1 m=n2t+1个数,m为偶数,所以对于二进制第t位1的个数和一定为偶数,可以不用考虑。转变为:
    f [ 2 t , n ] = f [ 0 , n − 2 t ] f[2^t,n] = f[0,n-2^t] f[2t,n]=f[0,n2t]
    因为n为奇数, 2 t 2^t 2t一定为偶数。所以 n − 2 t n-2^t n2t是一个奇数,所以可以不断缩小n。
    f [ 0 , n ] = f [ 0 , n − 2 t ] = f [ 0 , n − 2 t − k 1 ∗ 2 t − 1 − k 2 ∗ 2 t − 2 ⋯ − k i ∗ 2 ] ( 2 ≤ t ) 。 = f [ 0 , p ] ( p ≤ 3 ) f[0,n] = f[0,n-2^t] = f[0,n-2^t-k_1*2^{t-1}-k_2*2^{t-2} \dots -k_i*2](2 \leq t)。= f[0,p](p\leq3) f[0,n]=f[0,n2t]=f[0,n2tk12t1k22t2ki2](2t)=f[0,p](p3) k i k_i ki代表这一位是否有值。
    因为t要大于等于2,所以只要单独考虑最后两位的情况。
    n&3 = 1 (01) 时, f [ 0 , n ] = f [ 0 , 1 ] = 1 f[0,n]=f[0,1] = 1 f[0,n]=f[0,1]=1 先手胜
    n&3 = 3 (11) 时, f [ 0 , n ] = f [ 0 , 3 ] = 0 f[0,n]=f[0,3] = 0 f[0,n]=f[0,3]=0 先手败

  2. n为偶数
    f [ 0 , n ] = f [ 0 , 2 t − 1 ] ⊕ f [ 2 t , n ] = f [ 2 t , n ] f[0,n] = f[0,2^t-1] \oplus f[2^t,n]=f[2^t,n] f[0,n]=f[0,2t1]f[2t,n]=f[2t,n]
    m = n − 2 t + 1 m=n-2^t+1 m=n2t+1为奇数, f [ 2 t , n ] = f [ 0 , n − 2 t ] ⊕ 2 t f[2^t,n]=f[0,n-2^t]\oplus2^t f[2t,n]=f[0,n2t]2t
    n − 2 t n-2^t n2t还是偶数,依旧可以缩小n
    f [ 0 , n ] = f [ 0 , n − 2 t − k 1 ∗ 2 t − 1 − ⋯ − k i ∗ 2 ] ⊕ 2 t ⊕ k 1 ∗ 2 t − 1 ⋯ ⊕ k i ∗ 2 f[0,n] = f[0,n-2^t-k_1*2^{t-1}-\dots-k_i*2]\oplus2^t\oplus k_1*2^{t-1}\dots \oplus k_i*2 f[0,n]=f[0,n2tk12t1ki2]2tk12t1ki2
    后面的常数项异或和就是n,
    n&3 只有2或者0
    n&3 = 2(10)时, f [ 0 , n ] = n + f [ 0 , 2 ] = n + 1 f[0,n]=n+f[0,2] = n+1 f[0,n]=n+f[0,2]=n+1
    n&3 = 0(00)时, f [ 0 , n ] n + f [ 0 , 0 ] = n f[0,n]n+f[0,0] = n f[0,n]n+f[0,0]=n

SG函数

定义mex{S}运算: 不在集合S中最小的非负整数。
例如: mex{0,2,3,4}=1,mex{1,2,3,4}=0。

对于任意状态x, S G ( x ) = m e x { S } SG(x) = mex\{S\} SG(x)=mex{S},S是x后继状态SG函数值的集合。
若x的后继三个SG函数值为 S G ( a ) , S G ( b ) , S G ( c ) SG(a),SG(b),SG(c) SG(a)SG(b)SG(c),那么 S G ( x ) = m e x { S G ( a ) , S G ( b ) , S G ( c ) } SG(x) = mex\{ SG(a), SG(b), SG(c) \} SG(x)=mex{SG(a),SG(b),SG(c)}

当x时终态时,后继状态为空, S G ( x ) = 0 SG(x) = 0 SG(x)=0,即为必败态。

有1堆n个的石子,每次只能取{ 1, 3, 4 }个石子,先取完石子者胜利,
那么各个数的SG值为多少?

SG(0) = 0, f[ ] = {1,3,4}

x = 1时,可取1个,剩余0个,SG(1) = mex{ SG(0) } = 1。
x = 2时,可取1个,剩余1个,SG(2) = mex{ SG(1) } = 0。
x = 3时,可取1个或3个,剩余2个或0个,SG(3) = mex{ SG(2), SG(0) } = 1。
x = 4时,可取1,3,4,剩余3,1,0,SG(4) = mex{ SG(3), SG(1), SG(0) } = 2。

可以发现,SG函数可以从小到大递推而来。

由上述实例我们就可以得到SG函数值求解步骤,那么计算1~n的SG函数值步骤如下:

  1. 使用 数组f 将 可改变当前状态 的方式记录下来。

  2. 然后我们使用 另一个数组 将当前状态x 的后继状态标记。

  3. 最后模拟mex运算,也就是我们在标记值中 搜索 未被标记值 的最小值,将其赋值给SG(x)。

  4. 我们不断的重复 2 - 3 的步骤,就完成了 计算1~n 的函数值。

一个游戏可以分解成两个子游戏a,b,那么即后继的状态为SG[a]^SG[b]的值

你可能感兴趣的:(博弈)