【bzoj1022】小約翰的遊戲John
阿新 • • 發佈:2018-08-05
https tps problem names href else ace other --
,由上段的論證我們可以發現,此時,無論先手如何決策,都只會將遊戲帶入先手必勝局,所以先手必敗
Portal -->bzoj1022
Solution
? ?這題其實是裸的反Nim,這裏主要是為了寫反Nim遊戲的證明
? ?首先給出反Nim(anti-nim)的定義和結論:
【定義】桌子上有 N 堆石子,遊戲者輪流取石子; 每次只能從一堆中取出任意數目的石子,但不能不取;取走最後一個石子者敗
【結論】先手必勝當且僅當滿足下面兩個條件中的一個
? ?(1)所有堆的石子數都為\(1\)且遊戲的\(sg\)值為\(0\)
? ?(2)有些堆的石子數大於\(1\)且遊戲的\(sg\)值不為\(0\)
? ? ?
? ?然後我們來證明anti-nim遊戲的結論,可以分成兩種情況討論(以下內容摘自論文):
1、每堆只有\(1\)個石子:
? ?那麽顯然先手必勝當且僅當石子堆數\(n\)為偶數
2、其他情況:
?? ?(1)當遊戲的\(sg\)值不為\(0\)時:若還有至少兩堆石子的數目大於$ 1$,則先手將 \(sg\)值變為 $0 \(即可;若只有一堆石子數大於\) 1$,則先手總可以將狀態變為有奇數個\(1\)(可以把大於\(1\)的那堆直接取完或者取剩\(1\)個),所以,當\(sg\)不為\(0\)時先手必勝
?? ?(2)當遊戲的\(sg\)值為\(0\)時:至少有兩堆石子的數目大於 \(1\),則先手決策完之後,必定至少有一堆的石子數大於 \(1\),且\(sg\)值(當前遊戲局面的)不為\(0\)
? ?
? ?代碼大概長這個樣子
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,T,ans,cnt; int main(){ #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); #endif int x; scanf("%d",&T); for (int o=1;o<=T;++o){ ans=0; cnt=0; scanf("%d",&n); for (int i=1;i<=n;++i){ scanf("%d",&x),ans^=x; if (x>1) ++cnt; } if (cnt==0) printf(n%2?"Brother\n":"John\n"); else printf(ans?"John\n":"Brother\n"); } }
【bzoj1022】小約翰的遊戲John