1. 程式人生 > >BZOJ 1022: [SHOI2008]小約翰的遊戲John (Anti-nim)

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

ant 所有 之前 自然 i++ page urn pen status

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; }

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