1. 程式人生 > >bzoj1022 [SHOI2008]小約翰的遊戲John

bzoj1022 [SHOI2008]小約翰的遊戲John

[SHOI2008]小約翰的遊戲John

Time Limit: 1 Sec Memory Limit: 162 MB

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


網上題解寫的特別好。。。只是我看不懂而已。。。
自己憑藉多年開車經驗瞎寫的。。。


//全為 1 的時候奇數個 1 先手必敗。 
//只有一個大於 1 的時候先手必勝
//也就是說現在要證明有兩個及以上大於 1 的時候如果 NIM和 == 0 後手必勝。
//除去特殊情況外所有情況一定能轉化到剛好有兩個大於 1 
//因為如果只有兩堆且他們一樣多的時候,顯然後手必勝
//也就是說如果說兩堆一樣多的話就看 1 的個數是奇數還是偶數,如果是奇數則先手勝。
//如果只有兩堆但是不一樣多的話先手必勝。
//同理可得兩堆不一樣多就看 1 的個數,偶數則先手勝。
//那麼最後的問題就變成了我們要判斷有大於兩個大於 1 的數的時候轉化到上面的情況誰先誰後。
//顯然 NIM和 == 0 的時候後手勝利(想一想就知道了) 

/*
綜上,先手必勝的條件是:
1.如果全為 1 則有偶數個 1 (NIM和 == 0)
2.只有一個大於 1
3.除上面兩種情況以後 NIM和 != 0 
*/ 
#include<bits/stdc++.h>
using namespace std;
int n, x, lin, all;

int main()
{
    int T; scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        lin = all = 0;
        for(int i = 1; i <= n; ++i){scanf("%d", &x); lin += (x > 1); all ^= x;}
        if(!lin && !all){printf("John\n"); continue;}
        if(lin == 1){printf("John\n"); continue;}
        if(lin > 1 && all){printf("John\n"); continue;}
        printf("Brother\n");
    } 
    return 0;
}