BZOJ 1022: [SHOI2008]小約翰的遊戲John (Anti-nim)

自為風月馬前卒發表於2018-02-23
Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3134  Solved: 2003
[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

 

裸的Anti-Nim遊戲

直接上定理

先手必勝的條件

所有堆的石子數都為1且遊戲的SG值為0

有些堆的石子數大於1且遊戲的SG值不為0

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e6+10,INF=1e9+10;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
    return x*f;
}
int a[MAXN];
main()
{
    #ifdef WIN32 
    freopen("a.in","r",stdin);
    #else
    #endif
    int QWQ=read();
    while(QWQ--)
    {
        int N=read(),one=0,allone=1,ans=0;
        for(int i=1;i<=N;i++)
        {
            a[i]=read();
            if(a[i]!=1) allone=0;
            if(a[i]>1)  one=1;
            ans=ans^a[i];
        }
        if( (ans==0&&allone) || (ans!=0&&one) ) printf("John\n");
        else    printf("Brother\n");
        
    }
    return 0;
}

 

相關文章