【题意分析】

  最简单的Anti-Nim博弈模型。

【解题思路】

  引理:SJ定理

对于一个Anti-Nim游戏,只要有以下两条条件之一,先手必胜:

1.游戏的总SG函数为0且任意子游戏的SG函数不超过1;

2.游戏的总SG函数不为0且至少存在一个子游戏的SG函数超过1。

证明:

定义xorsum(x)(Q)为满足布尔表达式Q的所有元素x的异或和。

设游戏总SG函数为X,子游戏的SG函数序列为L,分四种情况:

(1)X=0且∀n≤1(n∈L)(必胜态)

(2)X=0且存在n∈L使n>1(必败态)

(3)X≠0且∀n≤1(n∈L)(必败态)

(4)X≠0且存在n∈L使n>1(必胜态)

对于情况(1),

  ∵X=0,∀n≤1

  ∴∑n=0(mod 2)即有偶数个1

  此时双方只能有唯一的走法,模拟即可知先手必胜。

对于情况(2),

  ∵X=0,存在n∈L使n>1

  ∴∑[n≤1]=0(mod 2)且xorsum(n)=0(n∈L,n>1)

  ∴∑[n>1]≥2即L至少有两个大于1的元素

  故此状态经过一次操作后必定转移到必胜态(4),即必败。

对于情况(3),同理于情况(1),但结果状态是必败。

对于情况(4),

  当存在唯一的n∈L使n>1时,总能转移成必败态(3);

  当存在至少两个n∈L使n>1时,

    设X的最高位为t=2k(k∈N),必定存在一个n∈L,使n and t=1,易知(n xor t)<n,可将n变为(n xor t),而剩下子游戏的总SG函数亦为(t xor n),故可以转化为必败态(2);

  综上,(4)为必胜态。

证毕。

  直接应用SJ定理即可,复杂度O(TN)。

【参考代码】

 1 #include <cstdio>
 2 #define REP(i,low,high) for(register int i=(low);i<=(high);++i)
 3 using namespace std;
 4 static int T,n; int a[55];
 5 int main()
 6 {
 7     for(scanf("%d",&T);T--;)
 8     {
 9         scanf("%d",&n); int sum=0; bool over=0;
10         REP(i,1,n)
11         {
12             int t; scanf("%d",&t),sum^=t,over|=t>1;
13         }
14         puts(bool(sum)==over?"John":"Brother");
15     }
16     return 0;
17 }
View Code

 

We Secure, We Contain, We Protect.