題解 P1247 取火柴遊戲

2022-05-07 21:27:09 字數 1223 閱讀 9871

題目鏈結

題目大意:\(nim\) 遊戲輸方案

博弈論,\(nim\) 遊戲

分析:首先\(nim\)和定理,\(nim\)遊戲存在先手必勝狀態,當且僅當\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n \neq 0\)

分析,首先最終狀態所有物品取完\(nim\)和顯然為\(0\),為必敗狀態,反過來對手就是必勝狀態了

對於\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n \neq 0\),我們假設\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n=k\),我們任選乙個\(a_i\)將其異或上\(k\)即可

根據定義,一定有奇數個\(a_i\)最高位和\(k\)最高位相同,因此異或後比原來小,是個合法操作

對於\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n = 0\),一定不存在一種方案使得操作後仍有\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n = 0\),因為這樣操作後兩數相等不是合法操作,也就是說

\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n \neq 0\)時是必勝狀態,它可以轉移到

\(a_1 \bigoplus a_2 \bigoplus a_3 \dots \bigoplus a_n = 0\)是必敗狀態

而必敗狀態只能轉移到必勝狀態,根據歸納法得證

再來看輸方案,我們列舉每乙個\(a_i\)檢查異或上\(k\)後是否合法即可

#include #include using namespace std;

const int maxn = 5e5 + 100;

inline int read()

int val[maxn],n,sum,ansa,ansb;

int main()

printf("%d %d\n",ansa,ansb);

val[ansb] -= ansa;

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

printf("%d%c",val[i],i == n ? '\n' : ' ');

return 0;

}

P1247 取火柴遊戲

輸入k及k個整數n1,n2,nk,表示有k堆火柴棒,第i堆火柴棒的根數為ni 接著便是你和計算機取火柴棒的對弈遊戲。取的規則如下 每次可以從一堆中取走若干根火柴,也可以一堆全部取走,但不允許跨堆取,也不允許不取。誰取走最後一根火柴為勝利者。例如 k 2,n1 n2 2,a代表你,p代表計算機,若決定...

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

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

洛谷P1247 取火柴遊戲 數學題 博弈論

這題就是nim取石子遊戲,但是nim取石子方案並不是單一的,而是有多種方案的,現在讓我們求字典序最小的方案,其實還是簡單的,作為先手,如果是必勝局面,那我們肯定第一步把所有子異或和變為零 這樣對於對方,這就是乙個必敗局面了 2 那我們來考慮怎麼把局面變成必敗局面呢,換句話說,怎麼判斷這一堆取不取呢,...