John(POJ 3480) 逆尼姆博弈
逆尼姆博弈
John
Little John is playing very funny game with his younger brother. There is one big box filled with M&Ms of different colors. At first John has to eat several M&Ms of the same color. Then his opponent has to make a turn. And so on. Please note that each player has to eat at least one M&M during his turn. If John (or his brother) will eat the last M&M from the box he will be considered as a looser and he will have to buy a new candy box.
Both of players are using optimal game strategy. John starts first always. You will be given information about M&Ms and your task is to determine a winner of such a beautiful game.
InputThe first line of input will contain a single integer T – the number of test cases. Next T pairs of lines will describe tests in a following format. The first line of each test will contain an integer N – the amount of different M&M colors in a box. Next line will contain N integers Ai, separated by spaces – amount of M&Ms of i-th color. Both of players are using optimal game strategy. John starts first always. You will be given information about M&Ms and your task is to determine a winner of such a beautiful game.
Constraints:
1 <= T <= 474,
1 <= N <= 47,
1 <= Ai <= 4747
OutputOutput T lines each of them containing information about game winner. Print “John” if John will win the game or “Brother” in other case.
Sample Input
2
3
3 5 1
1
1
Sample Output
John Brother
题意:有N堆石子每堆任意多个,每次可以从其中一堆中取出任意多个,最后取的人输。
题解:
我们可以知道,如果有一堆多于1的石子个数为m,我们通常做法是将其中的m-1个石子取走,将只剩下1个石子的状态留给对方,那么先手必胜。那么
这个题的状态便一共有以下几种:
(1)所有堆石子个数均为1
稍微模拟一下就知道,如果堆数为奇数,那么先手必败,如果堆数为偶数,先手必胜。
(2)有一堆石子个数大于1
如果剩下的个数为1的堆的个数为奇数,先手可以从这堆个数大于1的堆中取走m-1,使其变成1,那么先手必胜;如果剩下的个数为1的堆的个数为偶数,
先手可以把这堆全取走,那么先手必胜。故有一堆石子大于1的状态先手必胜。
(3)有多于一堆的石子个数大于1
<3.1 所有堆石子个数的抑或和为0
这种情况下,可转移堆状态只有两种:
① 变成只有一堆石子个数大于1且抑或和不为0 如(1 2 3)->(1 1 3)
这种状态和(2)相同,先手必胜。
② 变成有多于1堆石子的抑或和不为0 如(1 2 3)->(1 2 2)
这种状态和<3.2相同,以下讨论。
<3.2 所有堆石子个数的抑或和不为0
这种状态一定存在一种取法将状态转化为<3.1或者(2) 至此我们可以知道,后手要么直接让先手胜,要么将相同堆<3.2状态交还给先手。
综上:面对<3.1状态的人必败,面对<3.2状态的人必胜。
即:当前局面为必胜态 等价于
所有堆的石子个数均为1且尼姆和等于0,或者至少有一堆石子个数大于1且尼姆和不为0。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 const int maxn=1e4+10;
6 int a[maxn];
7 int sg[maxn];
8 int main()
9 {
10 int casen;
11 int n;
12 cin>>casen;
13 while(casen--)
14 {
15 memset(sg,0,sizeof(sg));
16 scanf("%d",&n);
17 int flag=0;
18 for(int i=0;i<n;i++)
19 {
20 scanf("%d",&a[i]);
21 if(a[i]!=1)
22 {
23 sg[i]=1;
24 flag++;
25 }
26 else
27 {
28 sg[i]=0;
29 }
30 }
31 if(flag==0)
32 {
33 if(n%2==1)
34 {
35 printf("Brother\n");
36 continue;
37 }
38 else
39 {
40 printf("John\n");
41 continue;
42 }
43 }
44 else if(flag==1)
45 {
46 printf("John\n");
47 continue;
48 }
49 else
50 {
51 int ans=0;
52 for(int i=0;i<n;i++)
53 ans^=a[i];
54 if(ans==0)
55 printf("Brother\n");
56 else
57 printf("John\n");
58 continue;
59 }
60 }
61 }