博弈论入门
写在前面
博弈论,又称为对策论(Game Theory)、赛局理论等,既是现代数学的一个新分支,也是运筹学的一个重要学科。——百度百科
巴什博弈
两个人在 \(n\) 个石子面前玩取石子游戏,每个人每次可以取 \([1,m]\) 个,不能拿的人为败者,为谁会获胜
- 当石子的数目不多于 \(m\) 个时,很显然先手会胜
- 当石子数为 \(m + 1\) 个时,先手必败(先手无论拿多少个,后手都会把剩下的石子都拿走)
我们不难发现,当一个人面对 \(m + 1\) 个石子的时候肯定会败
于是乎,就得到了制胜秘诀
- 当石子数量 \(n = k * (m + 1) + r\) 时,先手先拿走 \(r\) 个石子,接着后者拿走 \(x\) 个石子,然后先手再拿走 \(m + 1 - x\) 个石子,这样下去先手必胜
- 当石子数量 \(n = k*(m + 1)\) 时,先手拿走 \(x\) 个石子,后者就会拿走 \(m + 1 - x\) 个石子,这样下去后者必胜
代码实现
if(n % (m+1) !=0) printf("first win");
else printf("second win");
P2197 nim 游戏
nim 游戏的规则是这样的:地上有 \(n\) 堆石子(每堆石子数量小于 \(10^4\) ),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。
假如甲是先手,且告诉你这 \(n\) 堆石子的数量,他想知道是否存在先手必胜的策略
solution
有条结论:所有堆的石子数异或为 0,则先手必败,否则先手必胜
证明
最终的败态显然是所有堆的石子都为 0
0 \(\bigoplus\) 0 \(\bigoplus\) 0 \(\bigoplus\) 0 \(\bigoplus\) 0……\(\bigoplus\) 0 = 0
如果起初石子的异或和不为 0,即
\(a_1 \bigoplus a_2 \bigoplus a_3… a_n= r\)
假设 \(r\) 的最高位为 \(k\) 则一定有一堆石子的第 \(k\) 位为 \(1\) ,那么先手就可以通过改变这堆石子来使得异或和为 0,那么后手就必败了
如果起初石子的异或和为 0,因为先手一定要拿石子,所以它就不能使得石子的异或和为 0了,所以先手必败
code
/*
work by:Ariel_
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
int read(){
int x = 0,f = 1; char c = getchar();
while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
return x*f;
}
int T, n, Ans;
int main(){
T = read();
while(T--) {
n = read();
Ans = read();
for (int i = 2, x; i <= n; i++) x = read(), Ans ^= x;
if(Ans == 0) printf("No\n");
else printf("Yes\n");
}
puts("");
return 0;
}
斐波那契博弈
一堆石子,两个人玩取石子游戏,先手第一次可以取任意多个,但是不能取完,以后每个人取得石子都不能超过上个人的两倍,不能取的那个人败
结论:当石子数为斐波那契数的时候,先手必败
威佐夫博弈
有两堆石子,两个人玩取石子游戏,每个人可以从一堆石子里取任意多个,也可以从两堆石子里面取相同多个石子,不能取的那个人败
假设两堆石子分别为 \(a,b\) 且 \(a < b\)
如果 \((b−a)∗\frac{(\sqrt5 + 1)}2=a\) 则先手必败

浙公网安备 33010602011771号