【题解】
首先,还是令SG[x]=x结论:
先手胜有两种情况:
1. Nim和(SG[i]异或和)==0,且每堆石子数量都为1
2. Nim和!=0,且至少有一堆石子数量大于1
简单证明(YY。。。):
反之,堆数为奇数时先手必败
情况2. 至少有一堆石子数量大于1时,
1)若只有一堆石子数量大于1(此时Nim和!=0),先手可一定可以将局面变为奇数个1,使后手进入必败状态
2)若有>=2堆石子数量大于1:初始的Nim和==0时:
*1 取石子相当于减小某个数,即把某个数的某个二进制位k由1变为0,再改变低于k的位数
*2 二进制位k为1的数有偶数
假设先手将某数a的最高第k位改为0,又改了k之后的某些位,那么后手完全可以也找到另一个二进制第k位为1的数b,
在第k位及之后做相同修改。若修改b之后,还存在大于1的数,就这样修改,并循环往复; 否则,后手完全可以不
修改b,而是转化为情况 2- 1) 的先手而取胜。此种情况后手必胜
初始的Nim和!=0时:先手可通过调整最大的数,将局面变为 Nim和==0,他就成为了上面情况的"后手"。此种情况先手必胜
注意:
SG!=0不能写成SG==1!!!
【代码】
#include<stdio.h>
#include<stdlib.h>
int main()
{
int T,n,i,x,SG,flag;
scanf("%d",&T);
for(;T>0;T--)
{
scanf("%d",&n);
SG=flag=0;//SG:异或和
for(i=1;i<=n;i++)
{
scanf("%d",&x);
SG^=x;
if(x!=1) flag=1;//flag==1:x不全为1
}
if( (SG==0&&flag==0) || (SG!=0&&flag==1) ) printf("John\n");
else printf("Brother\n");
}
return 0;
}