数论:博弈论
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先手赢,否则后手赢,偶数先手,奇数后手
题目导航
1.巴什博弈
HDU 2147 kiki's game HDU 2149 Public Sale HDU 1846 Brave Game HDU 2188 悼念512汶川大地震遇难同胞——选拔志愿者
2.威佐夫博奕
HDU 1527 取石子游戏
3.尼姆博奕
洛谷
4.斐波那契博弈
HDU 2516 取石子游戏
5.环形博弈
hud3951