Loading

博弈论入门

写在前面

博弈论,又称为对策论(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\) 则先手必败

证明 要用到 Beatty 定理 没大有用 = =

posted @ 2021-07-11 09:56  Dita  阅读(193)  评论(0)    收藏  举报