Solution
这题其实是裸的反Nim,这里主要是为了写反Nim游戏的证明
首先给出反Nim(anti-nim)的定义和结论:
【定义】桌子上有 N 堆石子,游戏者轮流取石子; 每次只能从一堆中取出任意数目的石子,但不能不取;取走最后一个石子者败
【结论】先手必胜当且仅当满足下面两个条件中的一个
(1)所有堆的石子数都为(1)且游戏的(sg)值为(0)
(2)有些堆的石子数大于(1)且游戏的(sg)值不为(0)
然后我们来证明anti-nim游戏的结论,可以分成两种情况讨论(以下内容摘自论文):
1、每堆只有(1)个石子:
那么显然先手必胜当且仅当石子堆数(n)为偶数
2、其他情况:
(1)当游戏的(sg)值不为(0)时:若还有至少两堆石子的数目大于$ 1$,则先手将 (sg)值变为 (0)即可;若只有一堆石子数大于(1),则先手总可以将状态变为有奇数个(1)(可以把大于(1)的那堆直接取完或者取剩(1)个),所以,当(sg)不为(0)时先手必胜
(2)当游戏的(sg)值为(0)时:至少有两堆石子的数目大于 (1),则先手决策完之后,必定至少有一堆的石子数大于 (1),且(sg)值(当前游戏局面的)不为(0),由上段的论证我们可以发现,此时,无论先手如何决策,都只会将游戏带入先手必胜局,所以先手必败
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,T,ans,cnt;
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x;
scanf("%d",&T);
for (int o=1;o<=T;++o){
ans=0; cnt=0;
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%d",&x),ans^=x;
if (x>1) ++cnt;
}
if (cnt==0) printf(n%2?"Brother
":"John
");
else printf(ans?"John
":"Brother
");
}
}