博弈论

博弈论基础介绍:

巴什博弈:

例子:

一堆石子 \(n\) 个,任意取 \([1-m]\) 个,问先手必赢/输。

分析:

分类进行考虑:

  1. \([1,m]\) 个,先手必赢。
  2. \(m+1\) 个,先手必输。
  3. \([m+2,2m]\) 先手可以拿走几个,剩下 \(m+1\) 个,先手必胜。

我们发现,面临 \(m+1\) 个石子的人一定失败。

进行推广:设当前石子数为 \(n=k*(m+1)+r\), 先手先拿走 \(r\) 个,无论后手怎么拿 \(x\) 个,先手一定可以拿走 \(m+1-x\) 个,这样后手一定失败。

反之,当 \((m+1)|n\) ,先手一定失败。

因此,只要不满足 \((m+1)|n\) ,就一定先手必胜,反之必败,直接判断即可。

\(nim\) 游戏

例子:

\(n\) 堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿),没法拿的人失败。问谁会胜利。

定理:

\(n\) 堆石子的数量异或和等于 \(0\) 时,先手必败,否则先手必胜.

证明:

必败状态:我们设 \(a[i]\) 表示 \(i\) 堆石子的数量。当前局面为:

\[0⊕0⊕0⊕⋯⊕0=0 \]

对于先手来说,如果当前局面为:

\[a_1⊕a_2⊕a_3⊕⋯⊕a_n=k \]

那么一定存在 \(a_i\) ,二进制表示在最高位 \(k\) 上为 \(1\)

我们将 \(a_i⊕k\) ,这样就变成了:

\[a_1⊕a_2⊕a_3⊕⋯⊕a_n⊕k=0 \]

我们只需要保证给后手的人所有石子异或值为0,即可获胜,此时先手必胜。

反之,一开始异或值为 \(0\) ,此时先手必败。

特殊情况:

有些题目,只能选择 \([1-m]\) 个石子,这就是 \(nim+bash\) ,只需要将所有的石子堆的石子数目同时模 \(m+1\),然后异或运算即可。

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");
posted @ 2021-09-15 17:09  Evitagen  阅读(109)  评论(0)    收藏  举报