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

[SHOI2008]小約翰的遊戲

是我 一個 根據 .... amp name getc 輸出 sin

Description

小約翰經常和他的哥哥玩一個非常有趣的遊戲:桌子上有n堆石子,小約翰和他的哥哥輪流取石子,每個人取的時候,可以隨意選擇一堆石子,在這堆石子中取走任意多的石子,但不能一粒石子也不取,我們規定取到最後一粒石子的人算輸。小約翰相當固執,他堅持認為先取的人有很大的優勢,所以他總是先取石子,而他的哥哥就聰明多了,他從來沒有在遊戲中犯過錯誤。小約翰一怒之前請你來做他的參謀。自然,你應該先寫一個程序,預測一下誰將獲得遊戲的勝利。

Input

本題的輸入由多組數據組成,第一行包括一個整數T,表示輸入總共有T組數據(T小於等於500)。
每組數據的第一行包括一個整數N(N小於等於50),表示共有N堆石子

接下來有N個不超過5000的整數,分別表示每堆石子的數目。

Output

每組數據的輸出占一行,每行輸出一個單詞。
如果約翰能贏得比賽,則輸出“John”,否則輸出“Brother”,請註意單詞的大小寫。

Solution:

在普通的Nim遊戲當中,若各堆石子數異或和不為0,則先手必勝
然而在本題中,取走最後的那顆石子人輸
我們來分情況討論
1.若當前每堆石子數都為1,且石子堆數為奇數,則先手必敗,為偶數,先手必勝
2.若某一堆石子數>1且各堆石子異或和不為0,則先手必勝
為什麽呢?(~不知道......) 我們來推導一下
結論1是很顯然的,我們就不再做出贅述,如何來證明結論2呢
根據普通的Nim遊戲可以知道,在先手必勝

的情況下,總是有某種策略可以讓局勢重新轉換為先手必勝的局勢(先後手在不斷變換),而先手必敗的局勢是只能通向先手必勝的。
又由於我是先手,則在雙方都采取先手必勝->先手必勝的策略的情況下,最後輸的總是我。
那麽轉換到本題,在滿足2條件的情況下,最後贏得肯定是我。
得證。

Code:

#include<bits/stdc++.h>
#define N 101
using namespace std;
int n,a[N];
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    int Case=read();
    begin:Case--;
    if(Case<0)return 0;
    n=read();memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++){
        a[i]=read();
        a[0]^=a[i];
    }
    sort(a+1,a+n+1);
    if((a[n]==1&&!a[0])||(a[0]&&a[n]>1))puts("John");
    else puts("Brother");
    goto begin;
}

[SHOI2008]小約翰的遊戲