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