數論:博弈論
1.巴什博弈(BAshGame)
題目模板
- 只有一堆n個物品
- 兩個人輪流取,每次只能取1~m個物品,誰先取完,誰勝利;(n,m是輸入的隨機數)
解題思路
1.當 n = m+1 時 第一個取的人不可能獲勝;
2.•當 n = k(m + 1) + r 時 (k,r,s都是未知的整數)*
•先取者拿走 r 個,那麼後者再拿(1~m)個
• 此時 n =(k-1)*(m+1)+s
•先取者再拿走s 個 最後總能造成 剩下n=k(m+1) 的局面*
3.•若n=k(m+1) 那麼先取者必輸*
求解巴什博弈函數
bool bash_g(int n,int m)
{
if(n%(m+1)!=0)
return true;
return false;
}
2.威佐夫博奕(Wythoff’s game)
題目模板
- 有兩堆各若干個
- 兩個人輪流從某堆或同時從兩堆取同樣多的物品
- 規定每次至少取一個,多者不限,最後取光的人勝利
解題思路
兩堆石子的狀態爲 [a,b] (滿足a<=b)
當 a=(k(√5+1)/2), b=a+k 時滿足奇異局勢,那麼則先手輸,反之則先手贏*
求解威佐夫博奕函數
bool Wythoff_Game(int a,int b)//b要大於a
{
double x=(1+sqrt(5))/2;
int k=b-a;
if(a==(int)(x*k))
return true;
return false;
}
3.尼姆博奕(Nimm’s Game)
題目模板
有多堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取一個,多者不限,最後取光者得勝。
解題思路
用0與每個數異或,如最後結果爲0,則後手勝
設一數組a[n][m],令sum=0
循環與數組每一個數據異或(sum^=a[i][j])
sum最後等於0則後手勝
求解尼姆博弈函數
a[m]每堆物品的數量 sum=0
int Nimm_Game(int n,int m)//n堆物品,m個物品
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
sum = sum ^ a[i][j];
if(sum == 0)
return 0;
return 1;
}
4.斐波那契博弈
題目模板
- 有一堆個數爲n的石子,遊戲雙方輪流取石子,
- 滿足:
- 先手不能在第一次把所有的石子取完;
- 之後每次可以取的石子數介於1到對手剛取的石子數的2倍之間(包含1和對手剛取的石子數的2倍)
求解斐波那契博弈函數 f[50]
int Fib_Game(int n)
{
f[1]=1;f[2]=1;
for(int i=3;i<=50;i++)
f[i] = f[i-1] + f[i-2];
if( 數組f 中包含 n )
return 1;//先手贏
return 0;
}
5.環形博弈
題目模板
n個石子圍成一個環,每次取一個或者取相鄰的2個(每個石子有序號)
求解
石子數<=2先手贏,否則後手贏,偶數先手,奇數後手