更好的閱讀體驗點這裡
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