1. 程式人生 > >Daizhenyang's Coin HDU - 3537

Daizhenyang's Coin HDU - 3537

文章目錄

Daizhenyang’s Coin HDU - 3537

題意: 若干個個硬幣排成一排,其中有n個是正的,其它都是反的,每一次你可以選擇1,2,3 個進行反轉,但是最右邊的硬幣必須是從正面到反面
SG函式可以用來求組合博弈問題

  1. 博弈的人數是兩個
  2. 有限步內結束
  3. 每個狀態的勝負與人無關

本題是Game theory 論文裡面例題
首先由x1,x2,x3 位置的硬幣為正,那麼他們滿足 S

G ( x 1 , x 2 , x
3
) = S g ( x 1 )
S G ( x 2 ) S G ( x 3 ) SG(x_1,x_2,x_3) = Sg(x_1 )\oplus SG(x_2) \oplus SG(x_3)

怎麼求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有以下運演算法則
O O = E , E E = E O \oplus O = E,E \oplus E = E
O E = O , E O = O O \oplus E = O, E \oplus O = O
我們發現SG(x) 的值是第x個O數
結論如下:

  1. 如果2 * x是O數,SG函式值為2*x
  2. 如果2 * x是E數, SG函式值是2*x+1

證明:

沒有硬幣是正的,終止態,SG = 0,是E數
最左邊的硬幣(位置從0開始)是的正的 S G ( 0 = 1 SG(0)= 1 ,是O數
假設對於前x的個數滿足證明,對於第x個數的SG值
選擇反轉一個硬幣到終止態SG(0) = 0
選擇反轉兩個硬幣,則可以轉移到 S G ( 1 ) , S G ( 2 ) , S G ( 3 ) . . . . . . S G ( x 1 ) SG(1),SG(2),SG(3)......SG(x-1) ,是小於2x的所有O數
選擇反轉三個硬幣,是 S G ( i ) S G ( j ) i ! = j i , j < x SG(i)\oplus SG(j) \quad i != j \quad i ,j < x ,是小於等於2
x的所有E數
所以有結論

  1. 如果2 * x是O數,SG函式值為2*x
  2. 如果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;
}