bzoj1022 [SHOI2008]小约翰的游戏John

1022: [SHOI2008]小约翰的游戏John

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 1621  Solved: 1025
[Submit][Status][Discuss]

Description

小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取,我们规定取到最后一粒石子的人算输。小约翰相当固执,他坚持认为先取的人有很大的优势,所以他总是先取石子,而他的哥哥就聪明多了,他从来没有在游戏中犯过错误。小约翰一怒之前请你来做他的参谋。自然,你应该先写一个程序,预测一下谁将获得游戏的胜利。

Input

本题的输入由多组数据组成,第一行包括一个整数T,表示输入总共有T组数据(T≤500)。每组数据的第一行包括一个整数N(N≤50),表示共有N堆石子,接下来有N个不超过5000的整数,分别表示每堆石子的数目。

Output

每组数据的输出占一行,每行输出一个单词。如果约翰能赢得比赛,则输出“John”,否则输出“Brother”,请注意单词的大小写。

Sample Input

2
3
3 5 1
1
1

Sample Output

John
Brother

HINT

 

【数据规模】

对于40%的数据,T ≤ 250。

对于100%的数据,T ≤ 500。

 

Source

Seerc2007

 

题意:给出n堆石头,每次可以取任意一堆的任意多石头(不能不取),问先手胜还是后手胜

分析:

博弈论

首先分析后得出有一种特殊情况

1、特殊情况:石头堆全是1个石头,这是显然奇数堆先手败, 偶数堆后手败

2、一般情况:存在一堆石头的个数大于1

分析一下:如果两堆石头一样(都大于1),即SG==0,其他石头都是1,那么后手就可以控制剩下的是奇数个石堆还是偶数个石堆

如果显然SG==0是必败态

那么如果面对SG != 0时,我们必然可以使SG变回 0

所以SG != 0 是必胜态

令Sg[x] = x,因为石堆石头为x时,能够一步变成 x-1,x-2,.....,1,0,符合Sg函数的定义

那么n堆石头的Sg就是这几个Sg[x]的异或值(将其写成二进制排在一起后在考虑如何取)

每次取都是Sg变回零显然是必胜策略

所以只需分两种情况考虑

 

综上所述,本题得解

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <ctime>
13 using namespace std;
14 typedef long long LL;
15 #define For(i, s, t) for(int i = (s); i <= (t); i++)
16 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
17 #define Rep(i, t) for(int i = (0); i < (t); i++)
18 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
19 #define MIT (2147483647)
20 #define INF (1000000001)
21 #define MLL (1000000000000000001LL)
22 #define sz(x) ((int) (x).size())
23 #define clr(x, y) memset(x, y, sizeof(x))
24 #define puf push_front
25 #define pub push_back
26 #define pof pop_front
27 #define pob pop_back
28 #define ft first
29 #define sd second
30 #define mk make_pair
31 inline void SetIO(string Name) {
32     string Input = Name+".in",
33     Output = Name+".out";
34     freopen(Input.c_str(), "r", stdin),
35     freopen(Output.c_str(), "w", stdout);
36 }
37 
38 int n, Sg;
39 bool Flag;
40 
41 inline void Solve();
42 
43 inline void Input() {
44     int Test;
45     scanf("%d", &Test);
46     while(Test--) {
47         scanf("%d", &n);
48         Solve();
49     }
50 }
51 
52 inline void Solve() {
53     int x;
54     Sg = 0, Flag = 0;
55     while(n--) {
56         scanf("%d", &x);
57         Sg ^= x;
58         Flag |= (x > 1);
59     }
60     if((!Sg && !Flag) || (Sg && Flag)) puts("John");
61     else puts("Brother");
62 }
63 
64 int main() {
65     SetIO("1022");
66     Input();
67     //Solve();
68     return 0;
69 }
View Code

 

posted @ 2015-07-08 11:36  yanzx6  阅读(150)  评论(0编辑  收藏  举报