取火柴遊戲 Nim博弈

2022-04-30 00:51:15 字數 1616 閱讀 5798

好久之前看的sg函式了

好像就記住乙個nim博弈qwq

第一次啊看的時候很迷,現在感覺可以了qwq

首先我們來看乙個其他的遊戲。(以下遊戲只有兩個人參與,且足夠聰明)

兩個人在一張圓形的桌子上放等大的盤子,最後乙個無法放盤子的人輸掉比賽

很顯然,先手必勝。

為什麼? 第乙個人可以將盤子放在桌子的中心。

然後只要第二個人可以放置盤子,我們就在其中心對稱的位置上放盤子。

如此,只要後手可以放,我先手就一定能放

可以看出,有時候如果處於先手必勝的狀態時,模仿對手的策略不妨是個好方法。這可以保證如果遊戲可以進行下去的話,先手就一定能進行下去。

我們再來看乙個更nim遊戲的弱化版

有兩個火柴堆,每堆的火柴數不一定相同,每次乙個人只能從一堆中選取若干個火柴並取走。沒有火柴可取的人輸

好像這和上個題沒有什麼關係qwq

我們假設兩個火柴堆的數目都相同。那麼肯定是先手必輸

為什麼?因為後手總可以從另一堆中取的和先手上一次取得一樣的火柴。

只要先手可以取,後手就可以取。

所有該遊戲的判定條件是,若兩堆相等,先手必輸,否則,先手必勝,先手總可以將兩堆取成一樣多

先手必勝時總有一種策略可以轉移到後手必敗

後手必敗總是會轉移到先手必勝

好像大佬如此說過

然後我們看van♂整版nim

p1247 取火柴遊戲

先說結論,若所有火柴堆異或起來的值為0的話,先手必敗,否則先手必勝

(ノ`⊿´)ノ為什麼和異或結合起來的啊喂

這是得益於毒瘤的二進位制和更毒瘤的異或

異或有乙個特殊的規律,就是一堆數異或時,若在同乙個二進位制位上1的個數是偶數,那麼這一位異或起來以後是0,否則為1

二進位制的話就是可以使用0/1表示所有數字

我們來看上乙個遊戲,我們將這兩堆的剩餘的火柴數轉變成二進位制。

發現我們先手取走乙個數,就是改變其二進位制為上的1的個數(只考慮奇偶性),而後手再去取的話就是將其奇偶性再變回來

然後我們再回去看為什麼異或和是0時先手必輸,因為先手拿走了某些火柴時,我們可以根據其拿走火柴的二進位制表示,在其他一堆中拿走一些一些數字,使得其異或和重新為0;

怎麼搞呢? 我們可以拿走一些數,也就是減某乙個數,使得先手拿完後,(囉嗦警告)

所有堆中的每個二進位製上的一的個數的和,我們總可以通過加減乙個數,達到在某乙個二進位制位的1的個數進行加一or減一的效果

使得某一位二進位製上的1的個數變為偶數。

從而使得遊戲又恢復到了一開始的局面

end......

sg函式好像也是這個思想qwq

此題**

#include#include#include#includeusing std::sort;

const int maxn=501000;

int data[maxn];

int main()

if(x==0)

for(int i=1;i<=n;i++)

if((data[i]^x)<=data[i])

for(int i=1;i<=n;i++)

printf("%d ",data[i]);

}

取火柴遊戲

玩完幾把遊戲後。突然想起了乙個比較老的遊戲 取火柴遊戲!遊戲規則簡單 不需要撿裝備,也沒有危險的空投。emm言歸正傳!有n根火柴,每人每次最多取4根火柴,最少取一根火柴。如果某人取到最後一根火柴,那麼恭喜你,輸了!emmm上 void quhuochai last last user if last...

取火柴遊戲

include include include using namespace std float num1 0 float num2 0 struct treenode class tree float chance treenode ptr void run tree tree1 protect...

洛谷 P1247 取火柴遊戲(nim 遊戲)

簡單說一下 nim遊戲 的博弈原理,先將 a i 轉化成二進位制數,那麼題目變成了每一次可以取走任意 a i 的 任意個 1sum 是所有 a i 的異或值如果 sum 0,說明有偶數個 1,先手拿 x,後手也拿 x,先手必敗如果 sum 0,我們考慮去掉一堆,這 n 1 堆相互異或得到的結果 re...