同nim相似,除了终止条件:
回顾nim游戏的终止条件:
取走最后一个石子者胜
而anti-nim游戏的终止条件:
取走最后一个石子者败
只有一字之差,但做法却千差万别。
分析ing……
先假设一种特殊的情况:所有的N堆石子堆都只有一颗石子。
很明显,先手必胜当且仅当N为偶数。
接下来就是不是特殊的情况的情况(绕):
首先SG函数的值仍然是n个石子堆的nim和,分是0和不是0讨论。
不是0:
再分类,只有一堆石子的石子数大于1和至少有两堆石子的石子数大于1。对于前者,那么我们总可以把当前状态转成所有石子堆都只有一颗石子且石子堆的个数为奇数的状况,所以先手肯定必胜,反之,先手也总有办法将该状态的SG的函数值为0,至于怎么弄是玩家的事,又不是我的事。SG函数
是0:
同上分类,此时如果至少有两堆石子的数目大于 1,则先手决策完之后,必定至少有一堆的石子数大于 1,且 SG 值不为 0,对方不是笨蛋(我们的组合游戏的一个规则就是双方都走最优策略),我们前面分析的必胜策略人家也会用,所以我们就是必败,如果只有一堆石子数目大于1然后SG值还是0,呵呵,你给我造出一个这个状态来,由上段的论证我们可以发现,此时,无论先手如何决策,都只会将游戏带入先手必胜局,所以先手必败。
所以根据上面严肃(真的很严肃,一点也不滑稽)的推论,可得到anti-nim游戏的规律:
先手必胜当且仅当:
( 1)所有堆的石子数都为 1 且游戏的 SG 值为 0;
( 2)有些堆的石子数大于 1 且游戏的 SG 值不为 0。
然而,这只是anti-nim游戏,对于更多有anti情况的组合游戏,情况会如何?
anti-SG游戏
给出定义:
Anti-SG 游戏规定, 决策集合为空的游戏者赢。
Anti-SG 其他规则与 SG 游戏相同。
没了。
接下来我们来看从anti-nim游戏中得到的规律,我们的想法,就是把它转换成使用与anti-SG游戏的规律:
先手必胜当且仅当:
1.所有单一游戏的SG值都为小于2 且游戏的 SG 值为 0;
2.至少有一个单一游戏的SG值大于1 且游戏的 SG 值不为 0。
接下来的事只有两种:证明,或者纠错。这次菜鸡fhj选择了后者,NANANA。
反例如下(From 组合游戏略述——浅谈 SG 游戏的若干拓展及变形 By 石家庄二中 贾志豪,本博客的核心都借(kao)鉴(bei)了这篇论文)
在绿点的状态下,原来是满足必胜规律1的,但是实际情况却是必败!!!
那怎么办?
膜拜论文作者啊(前面提到过的),对于anti-SG游戏,他提出了一种基于前面内容的全新定理(具体来说就是排除某些特殊情况),并把它命名为——SJ定理(Sprague Grundy——Jia Zhihao 定理)。(lalala)
如果你感到上面这一句话很无聊很恶心的话,没事,我也这么觉得,但该学的还是要学。
SJ定理(依旧From论文):
对于任意一个 Anti-SG 游戏, 如果我们规定当局面中所有的单一游戏的 SG 值为 0 时, 游戏结束,此时决策集合为空的选手获胜,则先手必胜当且仅当:
(1)游戏的 SG 函数不为 0 且游戏中某个单一游戏的 SG 函数大于 1;
(2)游戏的 SG 函数为 0 且游戏中没有单一游戏的 SG 函数大于 1。
证明略,反正都是copy来的,干脆把论文地址给出。
anti-nim裸题……
#include<cstdio>
int tst,n;
inline void readi(int &x){
x=0; char ch=getchar();
while ('0'>ch||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
int main()
{
readi(tst);
while (tst--){
readi(n); bool pd=false; int x=0,y;
for (int i=1;i<=n;i++){
readi(y); x^=y; if (y>1) pd=true;
}
if ((pd&&(x>0))||(!pd)&&(!x)) printf("John\n");
else printf("Brother\n");
}
return 0;
}