我是靠谱客的博主 悲凉便当,最近开发中收集的这篇文章主要介绍尼姆游戏(SG函数解决变形),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题意:
给定 n n n个石子堆,每堆有 a i a_i ai个石子( a i > 0 a_i>0 ai>0),每次可以选择一堆石子,从这堆石子中选择任意多的石子。两者皆采取最优策略,问什么状态下先手必败,什么状态下先手必胜。

题解:
经典尼姆游戏。
a 1 ⊕ a 2 ⊕ a 3 ⊕ . . . ⊕ a n − 1 ⊕ a n = 0 a_1oplus a_2oplus a_3oplus ...oplus a_{n-1}oplus a_n=0 a1a2a3...an1an=0,先手必败。
a 1 ⊕ a 2 ⊕ a 3 ⊕ . . . ⊕ a n − 1 ⊕ a n ≠ 0 a_1oplus a_2oplus a_3oplus ...oplus a_{n-1}oplus a_nneq 0 a1a2a3...an1an=0,先手必胜。

证明:定义 s u m = a 1 ⊕ a 2 ⊕ a 3 ⊕ . . . ⊕ a n − 1 ⊕ a n sum=a_1oplus a_2oplus a_3oplus ...oplus a_{n-1}oplus a_n sum=a1a2a3...an1an
终态一定是所有石子堆的石子个数都为 0 0 0,即 s u m = 0 sum=0 sum=0时。

这里推测:

  • s u m = 0 sum=0 sum=0时,先手必败
  • s u m ≠ 0 sumneq 0 sum=0时,先手必胜

证明:
考虑先手处于必胜态时,此时 s u m ≠ 0 sumneq 0 sum=0,那么先手必然要拿掉一些石子使得后手面临必败态,即先手拿掉一些石子后使得 s u m = 0 sum=0 sum=0
这里令被操作的石子堆是第 i i i堆,操作前的剩余 n − 1 n-1 n1堆石子异或值为 H = s u m ⊕ a i H=sumoplus a_i H=sumai,若将第 i i i堆石子数量降至 H H H,则 H ⊕ H = 0 Hoplus H=0 HH=0,此时后手将面临必败态。

问题转化为了寻找一个 a i a_i ai,使得 a i > H a_i>H ai>H
这里对于 s u m sum sum的二进制最高位 k k k,必然也是一个数 a i a_i ai的二进制最高位,那么选择该 a i a_i ai H H H必然比 a i a_i ai小,因此必然存在这样一个数使得 a i > H a_i>H ai>H
证毕。


以上是对于经典尼姆游戏的证明。
那么若限制每次拿石子的个数为指定集合中的任意一个数,如何解决判断必败态和必胜态。

考虑 S G SG SG函数的构造。(具体的 S G SG SG函数介绍省略。)

直接给出结论:
s u m = S G ( a 1 ) ⊕ S G ( a 2 ) ⊕ S G ( a 3 ) ⊕ . . . ⊕ S G ( a n − 1 ) ⊕ S G ( a n ) sum=SG(a_1)oplus SG(a_2)oplus SG(a_3)oplus ...oplus SG(a_{n-1})oplus SG(a_n) sum=SG(a1)SG(a2)SG(a3)...SG(an1)SG(an)
这里仍然推测:

  • s u m = 0 sum=0 sum=0时,先手必败
  • s u m ≠ 0 sumneq 0 sum=0时,先手必胜

考虑到 S G SG SG函数的定义, S G ( a i ) SG(a_i) SG(ai)可以到达任意小于 S G ( a i ) SG(a_i) SG(ai),即上一个模型,证明与尼姆游戏的普通版本一样。问题转化为了如何求解 S G SG SG函数。

给出一个以 f i b fib fib数列作为可取石子的个数集合的 S G SG SG函数的模板: h d u 1848. hdu1848. hdu1848.

int fib[17] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987};
int sg(int x) {
    if(~f[x]) return f[x];
    
    bool jud[M]; //M指的是需要的最大sg参数
    memset(jud, false, sizeof jud);
    for(int i = 1; i <= 15 && x >= fib[i]; ++i) jud[sg(x - fib[i])] = true;
    for(int i = 0; ; ++i) if(!jud[i]) return f[x] = i;
}

最后

以上就是悲凉便当为你收集整理的尼姆游戏(SG函数解决变形)的全部内容,希望文章能够帮你解决尼姆游戏(SG函数解决变形)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部