博弈論入門之nim遊戲

更好的閱讀體驗點這裏html

nim遊戲

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

nim遊戲是巴什博奕的升級版(不懂巴什博奕的能夠看這裏)code

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

若是說巴什博奕僅僅博弈論的一個引子的話,blog

nim遊戲就差很少算是真正的入門了遊戲

博弈分析

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

當只有一堆石子的時候,先手能夠所有拿走。先手必勝it

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

當有三堆的時候呢?入門

當有\(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

題解

相關文章
相關標籤/搜索