只是一道nim(尼姆博弈)題;
尼姆博弈模型,是acm題中常見的組合遊戲中的一種,大致上是這樣的:
有3堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取1個,多者不限,最後取光者得勝
這種情況最有意思,它與二進位制有密切關係,我們用(a,b,c)表示某種局勢,首先(0,0,0)顯然是必敗態,無論誰面對(0,0,0) ,都必然失敗;第二種必敗態是(0,n,n),自己在某一堆拿走k(k ≤ n)個物品,不論k為多少,對方只要在另一堆拿走k個物品,最後自己都將面臨(0,0,0)的局勢,必敗。仔細分析一下,(1,2,3)也是必敗態,無論自己如何拿,接下來對手都可以把局勢變為(0,n,n)的情形。
計算機演算法裡面有一種叫做按位模2加,叫做異或的運算,我們用符號xor表示這種運算,這種運算和一般加法不同的一點是1 xor 1 = 0。先看(1,2,3)的按位模2加的結果:
1 = 二進位制01
2 = 二進位制10
3 = 二進位制11 xor
———————
0 = 二進位制00 (注意不進製)
對於奇異局勢(0,n,n)也一樣,結果也是0。
任何奇異局勢(a,b,c)都有a xor b xor c = 0。
如果我們面對的是乙個非必敗態(a,b,c),要如何變為必敗態呢?假設 a < b < c,我們只要將 c 變為a xor b,即可。因為有如下的運算結果:
a ^ b ^ (a ^ b)=(a ^ a) ^ (b ^ b) = 0 ^ 0 = 0。
要將c 變為a ^ b,只要對 c進行 c-(a ^ b)這樣的運算即可。
尼姆博弈模型可以推廣到:有n堆若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取乙個,多者不限,最後取光者得勝。
這個遊戲中的變數是堆數k和各堆的物品數n1,n2,……,nk。對應的組合問題是,確定先手獲勝還是後手獲勝以及兩個遊戲人應該如何取物品才能保證自己獲勝(獲勝策略)
為了進一步理解nim取物品遊戲,我們考查某些特殊情況。如果遊戲開始時只有一堆物品,先手則通過取走所有的物品而獲勝。現在設有2堆物品,且物品數量分別為n1和n2。遊戲者取得勝利並不在於n1和n2的值具體是多少,而是取決於它們是否相等。設n1!=n2,
view code
#include#include先手從大堆中取走的物品使得兩堆物品數量相等,後手再拿,於是,先手以後每次取子的數量與後手相等而最終獲勝。但是如果n1= n2,則:後手只要按著先手拿的數量在另一堆中取相等數量的物品,最終獲勝者將會是後手。這樣,兩堆的取子獲勝策略就已經找到了。#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
int num[200024
];int
main( )
if( x == 0 ) printf( "
no\n");
else
} }}
//system( "pause" );
return0;
}
現在我們如何從兩堆的取子策略擴充套件到任意堆數中呢?
首先來回憶一下,每個正整數都有對應的乙個二進位制數,例如:57(10) = 111001(2) ,即:57(10)=25+24+23+20。於是,我們可以認為每一堆物品數由2的冪數的子堆組成。這樣,含有57枚物品大堆就能看成是分別由數量為25、24、23、20的各個子堆組成。
HDU 2176 取 m堆 石子遊戲
尼姆博弈。講解 有三堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取乙個,多者不限,最後取光者得勝。這種情況最有意思,它與二進位制有密切關係,我們用 a,b,c 表示某種局勢,首先 0,0,0 顯然是奇異局勢,無論誰面對奇異局勢,都必然失敗。第二種奇異局勢是 0,n,n 只要與對手拿...
HDU 2176 取 m堆 石子遊戲
hdu 2176 取 m堆 石子遊戲 problem description m堆石子,兩人輪流取.只能在1堆中取.取完者勝.先取者負輸出no.先取者勝輸出yes,然後輸出怎樣取子.例如5堆 5,7,8,9,10先取者勝,先取者第1次取時可以從有8個的那一堆取走7個剩下1個,也可以從有9個的中那一堆...
HDU2176取 m堆 石子遊戲
hdu2176取 m堆 石子遊戲 problem description m堆石子,兩人輪流取.只能在1堆中取.取完者勝.先取者負輸出no.先取者勝輸出yes,然後輸出怎樣取子.例如5堆 5,7,8,9,10先取者勝,先取者第1次取時可以從有8個的那一堆取走7個剩下1個,也可以從有9個的中那一堆取走...