SRM div1 MagicNim(博弈論)
題目大意:
給出n+1堆石子,前n堆石子的數量是a[i],最後一堆只有1個石子,但是具有魔力
拿走該石子的一方可以選擇接下來是進行普通的Nim遊戲還是anti-nim遊戲
問是先手必勝還是必敗
首先拿全是1的情況熟悉一下規則
如果全是1,那麽無論有幾堆,先手都是必勝的
因為如果有奇數個1,那麽Alice直接拿掉魔力石子,然後選擇不改變遊戲,那麽他還是贏的
如果有偶數個1,那麽Alice直接拿掉魔力式子,然後選擇改變遊戲,於是他還是贏的。
然後回憶一下anti-nim的先手必勝條件(這裏的SG不考慮多魔法石子的那一堆)
SG為0,且所有石子均為1
SG不為0,且存在一堆石子大於1
所以,如果不全是1,且SG為0的話,Alice是必輸的,因為他取魔力石子後,仍然無法改變必輸的情況
所以現在情況只有不全是1,且SG不為0
註意到這個時候任何一方如果直接取魔力石子,都是必敗的
所以雙方應該會保持SG不為0,然後進行對峙
首先考慮所以石子的數量不超過3
那麽SG函數的值就只有3個,1,2,3
當SG為1或3的時候,肯定有一種取法使得SG為2
而SG為2的最終情況是2附加一個魔力石子,這種情況是必敗的
所以當石子的數量不超過3時,SG=2先手必敗,反之必勝
接下來考慮石子的數量超過3,也就是有4和4以上的數
那麽SG函數的值可以分成1和超過1的那些情況
如果當前SG值為1,那麽只能把它變成超過1的值,然而對手又可以把它變回到1
我們考慮假設只有1個超過3的數,那麽這時候SG值肯定是大於3的
直接改變這個數,我們可以使得接下來的局面變成SG=2
也就是說,如果只有1個超過3的數,那麽就是先手必勝
那麽如果SG值為1,且我們知道存在超過3的數,那麽超過3的數的數量必定至少有2個
也就是說,經過不斷地對峙,原來SG值為1的話,現在SG值仍然為1
但是經過了很多減少,一定會達到這個局面
即SG值為1,且超過3的數量只有2個
當這2個其中的一個數減到4以下時,就變成了只有1個超過3的數
即SG->1->3以上->2(最終結果)
也就是說SG如果為1,必定會轉化成2,那麽SG=1就是必敗局面,而其他情況是必勝局面
最後結論就是
如果有大於3的數,那麽SG=1必敗
如果沒有,那麽SG=2必敗
(PS:題解的思路沒有太明白,不知道是怎麽想到右移1位然後分類的,然後莫名分類就分出來了orz)
#include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <typeinfo> #include <fstream> using namespace std; class MagicNim { public: string findWinner(vector<int> a) { sort(a.begin(), a.end()); int n = a.size(), sg = 0; for(int i = 0; i < n; i++) sg ^= a[i]; if(a[n-1] >= 4) return (sg == 1 ? "Bob" : "Alice"); else return (sg == 2 ? "Bob" : "Alice"); } };
SRM div1 MagicNim(博弈論)