bzoj1022 [SHOI2008]小约翰的游戏John
1022: [SHOI2008]小约翰的游戏John
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1621 Solved: 1025
[Submit][Status][Discuss]
Description
小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取,我们规定取到最后一粒石子的人算输。小约翰相当固执,他坚持认为先取的人有很大的优势,所以他总是先取石子,而他的哥哥就聪明多了,他从来没有在游戏中犯过错误。小约翰一怒之前请你来做他的参谋。自然,你应该先写一个程序,预测一下谁将获得游戏的胜利。
Input
本题的输入由多组数据组成,第一行包括一个整数T,表示输入总共有T组数据(T≤500)。每组数据的第一行包括一个整数N(N≤50),表示共有N堆石子,接下来有N个不超过5000的整数,分别表示每堆石子的数目。
Output
每组数据的输出占一行,每行输出一个单词。如果约翰能赢得比赛,则输出“John”,否则输出“Brother”,请注意单词的大小写。
Sample Input
3
3 5 1
1
1
Sample Output
Brother
HINT
【数据规模】
对于40%的数据,T ≤ 250。
对于100%的数据,T ≤ 500。
Source
题意:给出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 }