好久之前看的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...