John
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 4407 Accepted Submission(s): 2520
Problem Description
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.
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.
Input
The
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.
Constraints:
1 <= T <= 474,
1 <= N <= 47,
1 <= Ai <= 4747
Constraints:
1 <= T <= 474,
1 <= N <= 47,
1 <= Ai <= 4747
Output
Output
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堆中取糖吃,每次可以在其中的一堆中取至少一个,谁取完所有的糖果就输了,问最后谁会赢?
此游戏可以简化为nim博弈模型:
今有若干堆火柴,两人依次从中拿取,规定每次只能从一堆中取若干根, 可将一堆全取走,但不可不取,最后取完者为负,求必胜的方法。
解法:定义:若所有火柴数异或为0,则该状态被称为利他态,用字母T表示;否则, 为利己态,用S表示。
定义:T态中,若充裕堆的堆数大于等于2,则称为完全利他态,用T2表示;若充裕堆的堆数等于0,则称为部分利他态,用T0表示。
[定理5]:S0态,即仅有奇数个孤单堆,必败。T0态必胜。
[定理6]:S1态,只要方法正确,必胜。
中间过程不再赘述:
结论:
必输态有: T2,S0
必胜态: S2,S1,T0.
必胜态: S2,S1,T0.
所以这题求出John的必输态即可.
#include <iostream> #include <cstring> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <map> using namespace std; int main() { int tcase; scanf("%d",&tcase); while(tcase--){ int n,sum = 0,v,_cnt=0,_cnt1=0; ///_cnt 代表孤单堆的数量,_cnt1 代表充裕堆的数量 scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&v); if(v==1) _cnt++; if(v>1) _cnt1++; sum^=v; } if(_cnt%2&&_cnt1==0||_cnt1>=2&&sum==0){ printf("Brother "); }else{ printf("John "); } } return 0; }