1. 程式人生 > >[Bzoj1022][SHOI2008]小約翰的遊戲John(博弈論)

[Bzoj1022][SHOI2008]小約翰的遊戲John(博弈論)

pan submit 博弈論 取數 n) 比賽 bmi http bbs

1022: [SHOI2008]小約翰的遊戲John


Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 2976 Solved: 1894
[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

分析:


好吧,我不講博弈論,講的太博大精深了。我會盡量講的通(bo)俗(da)易(jing)懂(shen),

設現在我們所有堆的石頭數量都為1。如果有奇數堆,我們是不是輸了。。。。設為情況①(必輸)

設現在我們所有堆的石頭數量都為1。如果有偶數堆,我們是不是贏了。。。。設為情況②(必贏)

(好吧上面兩個解釋太白癡了。)

設現在我們有一堆石頭數量不為2,其他石頭都為1.

如果我們有奇數堆數量為1的石頭,我們只用把那一堆數量不為2的石頭取完,對面就會面臨情況①。然後你就贏了2333.

如果我們有偶數堆數量為1的石頭,我們只用把那一堆數量不為2的石頭變成1,對面就會面臨情況①。然後你就贏了2333.

我們把上面兩種情況設為情況③(必贏)。

(是不是也很白癡)

好吧,我們再來看另外的情況,我們現在有大於等於2堆石頭數量不為2.

如果此時所有石頭異或和為奇數我們設為情況④

如果此時所有石頭異或和為偶數我們設為情況⑤

如果石頭異或和為奇數,我們可以取數量最多的那堆,使異或和變成偶數。此時④可以變成⑤

如果石頭異或和為偶數,我們必須取,此時異或和一定變為奇數,⑤又變成了④。然後我們是不是還可以取完一堆石頭,也就可能變成③。

所以情況④使對面狀態變成⑤,情況⑤會使對面面臨狀態⑤或③。

所以④(必贏),⑤(必輸)。

好了我們就知道了:②③④必贏,①⑤必輸,沒了。

AC代碼:


# include <cstdio>
using namespace std;
int T,n,ans,x,num;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        ans = num = 0;
        for(int i = 1;i <= n;i++){
            scanf("%d",&x);
            if(!x)continue;
            ans ^= x;
            if(x >= 2)num++;
        }
        if((!num && !ans) || (ans && num))puts("John");
        else puts("Brother");
    }
}

[Bzoj1022][SHOI2008]小約翰的遊戲John(博弈論)