Daizhenyang's Coin HDU - 3537
阿新 • • 發佈:2018-11-05
文章目錄
Daizhenyang’s Coin HDU - 3537
題意: 若干個個硬幣排成一排,其中有n個是正的,其它都是反的,每一次你可以選擇1,2,3 個進行反轉,但是最右邊的硬幣必須是從正面到反面
SG函式可以用來求組合博弈問題
- 博弈的人數是兩個
- 有限步內結束
- 每個狀態的勝負與人無關
本題是Game theory 論文裡面例題
首先由x1,x2,x3 位置的硬幣為正,那麼他們滿足
怎麼求SG(x) 的值呢
經過打表發現SG(x) 的函式值不是2x+1,就是2x,這個規律是什麼呢?
position x : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...
g(x) : 1 2 4 7 8 11 13 14 16 19 21 22 25 26 28 ...
定義兩個數,暫且稱之為 O( odious ),E(evil),
O: 代表x的二進位制表達裡面有奇數個1
E: 代表x的二進位制表達裡面有偶數個1
有一些特殊的庫函式用G++編譯的時候支援以下操作
__builtin_parity(a) 直接返回a的二進位制表達中1的個數的奇偶性,如果有奇數個,返回1,否則返回0
O,E有以下運演算法則
我們發現SG(x) 的值是第x個O數
結論如下:
- 如果2 * x是O數,SG函式值為2*x
- 如果2 * x是E數, SG函式值是2*x+1
證明:
沒有硬幣是正的,終止態,SG = 0,是E數
最左邊的硬幣(位置從0開始)是的正的
,是O數
假設對於前x的個數滿足證明,對於第x個數的SG值
選擇反轉一個硬幣到終止態SG(0) = 0
選擇反轉兩個硬幣,則可以轉移到
,是小於2x的所有O數
選擇反轉三個硬幣,是
,是小於等於2x的所有E數
所以有結論
- 如果2 * x是O數,SG函式值為2*x
- 如果2 * x是E數, SG函式值是2*x+1
參考程式碼
int main(void)
{
int n;
while(cin>>n){
int sum = 0;
map<int,int> ma;
for(int i = 0;i < n; ++i){
int a;
scanf("%d",&a);
if(ma[a]) continue;
ma[a] = 1;
if(__builtin_parity(2*a))
sum ^= 2*a;
else
sum ^= 2*a+1;
}
if(sum == 0)
puts("Yes");
else
puts("No");
}
return 0;
}