博弈論入門之nim遊戲

自為風月馬前卒發表於2018-02-22

更好的閱讀體驗點這裡

nim遊戲

nim遊戲
有兩個頂尖聰明的人在玩遊戲,遊戲規則是這樣的:
\(n\)堆石子,兩個人可以從任意一堆石子中拿任意多個石子(不能不拿),沒法拿的人失敗。問誰會勝利

nim遊戲是巴什博奕的升級版(不懂巴什博奕的可以看這裡)

它不再是簡單的一個狀態,因此分析起來也棘手許多

如果說巴什博奕僅僅博弈論的一個引子的話,

nim遊戲就差不多算是真正的入門了

博弈分析

面對新的博弈問題,我們按照套路,從簡單的情況入手

當只有一堆石子的時候,先手可以全部拿走。先手必勝

當有兩堆石子且石子個數相同的時候,先手不論拿多少,後手都可以從另一堆中拿同樣多的石子,先手必敗,否則先手必勝

當有三堆的時候呢?

當有\(n\)堆的時候呢?

這樣玩下去確實是很繁瑣,不過前輩們總結出了一條非常厲害的規律!

定理解析

定理

對於nim遊戲,前輩們發現了一條重要的規律!

\(n\)堆石子的數量異或和等於\(0\)時,先手必勝,否則先手必敗

證明

\(\oplus\)表示異或運算

nim遊戲的必敗態我們是知道的,就是當前\(n\)堆石子的數量都為零

\(a[i]\)表示第\(i\)堆石子的數量,那麼當前局面就是

$0 \oplus 0 \oplus 0 \oplus \dots \oplus 0 = 0 $

  • 對於先手來說,如果當前局面是

\(a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_n = k\)

那麼一定存在某個\(a_i\),它的二進位制表示在最高位\(k\)上一定是\(1\)

我們將\(a_i \oplus k\),這樣就變成了

\(a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_n \oplus k = 0\)

此時先手必勝

  • 對於先手來說,如果當前局面是

\(a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_n = 0\)

那麼我們不可能將某一個\(a_i\)異或一個數字後使得

\(a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_n = 0\)

此時先手必敗

程式碼

#include<cstdio>
using namespace std;
int a[10001]; 
int main()
{
    int Test;
    scanf("%d",&Test);
    while(Test--)
    {
        int ans=0,N;
        scanf("%d",&N);
        for(int i=1;i<=N;i++) scanf("%d",&a[i]);
        for(int i=1;i<=N;i++) ans=ans^a[i];
        ans==0?printf("No\n"):printf("Yes\n");
    }
    return 0;
}

題目

臨時還沒有做太多題目,以後做多了慢慢補吧

題解

估計沒幾個人能一眼秒吧233

題解

相關文章