bzoj1022: [SHOI2008]小約翰的遊戲John(博弈SG-nim遊戲)
阿新 • • 發佈:2018-03-02
mat flag enter int ans problem blank 入門題 pos
1022: [SHOI2008]小約翰的遊戲John
題目:傳送門
題目大意:
一道反nim遊戲,即給出n堆石子,每次可以取完任意一堆或一堆中的若幹個(至少取1),最後一個取的LOSE
題解:
一道很不錯的題目啊,感覺可以作為一道很好的入門題
讀前一戳:博弈論文 && POPQQQ大佬%%%
大體要分為三種情況來討論:
1、全是為1的石子堆,如有偶數堆則先手勝,反之後手勝
2、有兩堆相同的石子且都不為1(後手獲勝的幾率很大):
那麽如果先手將其中一堆取剩1,那麽後手就可以將另一堆取完,此時後手勝
如果先手將其中一堆取完,那麽後手就可以將另一堆取剩1,還是後手勝
如果先手僅拿走其中一堆的一部分,那麽後手可以進行相同的操作,將另一堆也拿走相同的數量(這是情況又回到了上面兩種)
3、如果異或和不為0,那麽對於一般的nim遊戲一定可以將石子堆變成僅剩兩堆相同的(平衡狀態xor=0),這時又如上面所述了
總結:
如果全是石子數為1,異或和為0則先手勝,反之後手勝
如果有不為1的,異或和不為0則先手勝,反之後手勝
代碼:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5#include<algorithm> 6 using namespace std; 7 int T,n; 8 int main() 9 { 10 scanf("%d",&T); 11 while(T--) 12 { 13 scanf("%d",&n);int x,ans=0;bool flag=true; 14 for(int i=1;i<=n;i++) 15 { 16 scanf("%d",&x);ans^=x; 17 if(x!=1)flag=false; 18 } 19 if(flag==true) 20 { 21 if(ans==0)printf("John\n"); 22 else printf("Brother\n"); 23 } 24 else 25 { 26 if(ans==0)printf("Brother\n"); 27 else printf("John\n"); 28 } 29 } 30 return 0; 31 }
bzoj1022: [SHOI2008]小約翰的遊戲John(博弈SG-nim遊戲)