首页 > 其他分享 >博弈论基础

博弈论基础

时间:2024-08-28 10:23:07浏览次数:15  
标签:博弈论 21 sg texttt 基础 34 oplus SG

前置知识

  • mex ⁡ \operatorname {mex} mex:没有出现过的最小自然数,如 mex ⁡ { 0 , 2 , 3 } = 1 \operatorname {mex} \{0,2,3\}=1 mex{0,2,3}=1。
  • ⊕ \oplus ⊕:按位异或。

前言

博弈类问题大致分为,公平组合游戏、非公平组合游戏(绝大多数的棋类游戏)、反常游戏。
只需要关注公平组合游戏 (ICG) \texttt{(ICG)} (ICG),反常游戏是公平组合游戏的变形,经济类博弈也不是博客所讨论的范围

  • 两个玩家轮流行动游戏方式一致
  • 两个玩家对状况完全了解
  • 游戏一定会在有限步数内分出胜负
  • 游戏以玩家无法行动结束

博弈的双方都被认为是神之个体,因为所有玩家对状况完全了解,且充分为自己打算,绝对理性
当局面确定,结果必然注定,并且没有任何随机的成分
游戏中的每一个状态,最终导致的结果也必然注定,只有必胜态、必败态,两种状态
这一类博弈问题的结果没有任何意外,一方可以通过努力去改变结果是不可能的,这一点是反直觉的。

  • 常用对数器打表来找规律。
  • 博弈论的题目就是 要干去干,去找规律,不要怕

巴什博弈 (Bash) \texttt{(Bash)} (Bash)

n n n 个的石头,每次操作可以拿走 [ 1 , m ] [1,m] [1,m] 个石头。拿到最后 1 1 1 个石头的人获胜(也就是不能拿石头的人输)。

这个问题特别简单,就是显然答案是如果 n n n 为 m + 1 m+1 m+1 的倍数那么先手输,否则先手赢。

sg \texttt{sg} sg 函数

接下来引入 sg \texttt{sg} sg 函数。

sg \texttt{sg} sg 表示当前状态的胜负情况。

有如下公式 s g ( A ) = mex ⁡ ( s g ( B ) ∣ A → B ) sg(A)=\operatorname {mex} (sg(B)|A\to B) sg(A)=mex(sg(B)∣A→B)。

式子中的 A A A 和 B B B 表示状态, A → B A\to B A→B 表示 A A A 状态可以达到 B B B状态。也就是说我们可以通过 A A A 能达到的状态的SG函数值推算出 A A A 的 S G SG SG 值。

如果 sg \texttt{sg} sg 值为 0 0 0 则表示先手输,否则先手赢。

数学归纳法证明:

  1. 最终状态 S G = 0 SG=0 SG=0。
  2. 对于任意一个必胜态 S G ≠ 0 SG\not=0 SG=0,存在一个后继态 S G = 0 SG=0 SG=0
  3. 对于任意一个必败态 S G = 0 SG=0 SG=0,不存在一个后继态 S G = 0 SG=0 SG=0。

e.g. \texttt{e.g.} e.g.:在巴什博奕中:当 m = 2 m = 2 m=2 时, sg[0]=0,sg[1]=1,sg[2],   sg[3]=0, ⋯ \texttt{sg[0]=0,sg[1]=1,sg[2], sg[3]=0,}\cdots sg[0]=0,sg[1]=1,sg[2], sg[3]=0,⋯。

FAQ \texttt{FAQ} FAQ:

  • Q: 不就是判断一个输赢吗?为什么要用一个 int \texttt {int} int,我 bool \texttt{bool} bool 也可以啊。
  • A: 是的,确实可以只有 bool \texttt{bool} bool,用 int \texttt{int} int 另有用途,我们下面会讲。

P2197 【模板】 (Nim) \texttt{(Nim)} (Nim) 游戏—— sg \texttt{sg} sg 多个独立的子问题的合并

题目描述

甲,乙两个人玩 nim \texttt{nim} nim 取石子游戏。

nim \texttt{nim} nim 游戏的规则是这样的:地上有 n n n 堆石子(每堆石子数量小于 1 0 4 10^4 104),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,且告诉你这 n n n 堆石子的数量,他想知道是否存在先手必胜的策略。

公式引入

若局面X由若干个子游戏 X 1 , X 2... X n X1,X2...Xn X1,X2...Xn 构成,则
S G ( x ) = S G ( X 1 ) ⊕ S G ( X 2 ) ⊕ ⋯ ⊕ S G ( X n ) SG(x)=SG(X_1)\oplus SG(X_2) \oplus \cdots\oplus SG(X_n) SG(x)=SG(X1​)⊕SG(X2​)⊕⋯⊕SG(Xn​)

数学归纳法证明:

  1. 最终局面成立
  2. ∀ X \forall X ∀X,所有后继局面可以取到 G ( X 1 ) ⊕ S G ( X 2 ) ⊕ ⋯ ⊕ S G ( X n ) − 1 G(X_1)\oplus SG(X_2) \oplus \cdots\oplus SG(X_n)-1 G(X1​)⊕SG(X2​)⊕⋯⊕SG(Xn​)−1,取不到 S G ( X 1 ) ⊕ S G ( X 2 ) ⊕ ⋯ ⊕ S G ( X n ) SG(X_1)\oplus SG(X_2) \oplus \cdots \oplus SG(X_n) SG(X1​)⊕SG(X2​)⊕⋯⊕SG(Xn​)

同样看做 Nim \texttt{Nim} Nim 游戏

设 S → S 1 S \rightarrow S_1 S→S1​

S ⊕ ( S ⊕ S 1 ) = S 1 S \oplus (S \oplus S_1) =S_1 S⊕(S⊕S1​)=S1​
设 ( S ⊕ S 1 ) (S \oplus S_1) (S⊕S1​) 最高位为 k k k,存在 A A A 使得 k k k 位为 1 1 1。

那么 A ⊕ ( S ⊕ S 1 ) < A A \oplus (S \oplus S_1) < A A⊕(S⊕S1​)<A,所以让 A A A 变成 A ⊕ ( S ⊕ S 1 ) A \oplus (S \oplus S_1) A⊕(S⊕S1​)就行了。

问题解答

显然对于每一个子问题,对于石头个数为 n n n, sg(n)=n \texttt {sg(n)=n} sg(n)=n。

所以 S G = ⊕ i = 1 n a i SG=\oplus_{i=1}^{n}a_i SG=⊕i=1n​ai​。判断 ⊕ i = 1 n a i 是否为零即可 \oplus_{i=1}^{n}a_i 是否为零即可 ⊕i=1n​ai​是否为零即可

代码

#include<bits/stdc++.h>
using namespace std;
int t, n, a;
signed main(){
	scanf("%d", &t);
	while (t--) {
		scanf ("%d", &n); int ans = 0;
		while (n--) scanf("%d", &a), ans ^= a;
		if (ans == 0) puts("No"); else puts("Yes");
	}
    return 0;
}

P4279 [SHOI2008] 小约翰的游戏

题目描述

甲,乙两个人玩 取石子游戏。

游戏的规则是这样的:地上有 n n n 堆石子(每堆石子数量小于 5000 5000 5000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就====了。假如甲是先手,且告诉你这 n n n 堆石子的数量,他想知道是否存在先手必胜的策略。

这一题唯一的区别是 最后没石子可取的人就赢了

题目解析

首先,如果 ∀ i \forall i ∀i 有 a i = 1 a_i=1 ai​=1,那么就是看 n n n 的奇偶性了。
其次,如果只有一个 a i ≠ 1 a_i\not=1 ai​=1,那么先手必赢 为什么
最后,因为要的是“只有一个 a i ≠ 1 a_i\not=1 ai​=1”,异或和不为 0 0 0, 所以只要抓住异或和不为 0 0 0 即可获胜,那么就转化为 (Nim) \texttt{(Nim)} (Nim) 游戏了。

示例代码

#include<bits/stdc++.h>
using namespace std;
int main() {
    int t, n, x, ans, sum;
    scanf("%d", &t);
    while (t--) {
        cin >> n, ans = sum = 0;
        for(int i = 1; i <= n; ++ i) scanf("%d", &x), ans ^= x, sum += x;
        if(sum == n) puts(n & 1 ? "Brother" : "John");
        else puts(ans ? "John" : "Brother");
    }
	return 0;
}

P6487 [COCI2010-2011#4] HRPA ——斐波那契博弈

前置知识

  1. 斐波拉契数列:
    F = { 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , . . . . . } F ( n ) = { 0 if  n = 0 1 if  n = 1 F ( n − 1 ) + F ( n − 2 ) if  n > 1 F = \{1,1,2,3,5,8,13,21,34,.....\}\\ F(n) = \begin{cases} 0 & \text{if } n = 0 \\ 1 & \text{if } n = 1 \\ F(n-1) + F(n-2) & \text{if } n > 1 \end{cases} F={1,1,2,3,5,8,13,21,34,.....}F(n)=⎩ ⎧​01F(n−1)+F(n−2)​if n=0if n=1if n>1​
  2. 齐肯多夫(Zeckendorf)定理:任何正整数都可以表示成若干个不连续的斐波那契数之和。如 4 = 1 + 3 ( 1 4=1+3(1 4=1+3(1 和 3 ) 3) 3) 不相邻。

证明:

  • 若正整数 n n n 为斐波那契数,得证。
  • 否则,先取 $ F_{t_1} $,其中 $ t_1 $ 满足 $ F_{t_1} < n < F_{t_1 + 1} $。
    • 令 $ n’ = n - F_{t_1} $,同上一步取出一个 $ F_{t_2} $ 满足 $ F_{t_2} < n’ < F_{t_2 + 1} $。
    • 只要证明 $ t_1 \neq t_2 + 1 $。考虑反证法:
      • 假设 $ t_1 = t_2 + 1 $,则第一步取出的应当是 $ t_1 + 1 $ 而不是 $ t_1 $。原因是 $ F_{t_1 + 1} = F_{t_1} + F_{t_1 - 1} $。

题目分析

如果 t t t 为斐波拉契数,那么必须全部取完。

设 $ n = F_{i b_t} $,我们把 $ n $ 看成 $ F_{i b_{t-1}} $ 和 $ F_{i b_{t-2}} $ 两堆。

  • 若第一步取的个数超过 $ F_{i b_{t-2}} $,则后手可以直接取完剩余石子。
  • 否则,该问题变成了一个规模更小的同样的问题。

考虑 $ n = 2 $ 的情况(即规模最小的情况),先手只能取 1,于是后手取 1获胜。

可以结合下面理解一下

比如 43 = 34 + 8 + 1 43=34+8+1 43=34+8+1 那么答案为 1 1 1。
首先取走 1 1 1,然后如果对方选择的数只能选择 [ 1 , 2 ] [1,2] [1,2]
假如对方取的是 2 2 2,那么 8 = 3 + 5 8=3+5 8=3+5,我选择把 3 3 3 消掉,我就选择 1 1 1。
这时数字变成了 34 + 5 34+5 34+5
对方又只能选择 [ 1 , 2 ] [1,2] [1,2], 假如他选择 1 1 1,那么 5 = 2 + 3 5=2+3 5=2+3,我就把 2 2 2消掉,选择 1 1 1
这时数字变成 34 + 3 34+3 34+3
对方又只能选择 [ 1 , 2 ] [1,2] [1,2], 假如他选择 2 2 2,那么我就把 3 3 3消掉,选择 1 1 1
这时数字变成 34 34 34
对方又只能选择 [ 1 , 2 ] [1,2] [1,2], 假如他选择 2 2 2,那么 34 = 21 + 8 + 5 34=21+8+5 34=21+8+5消掉,我就把 5 5 5 消掉,选择 3 3 3
这时数字变成 21 + 8 21+8 21+8
对方又只能选择 [ 1 , 6 ] [1,6] [1,6], 假如他选择 6 6 6,那么 29 = 21 + 8 29=21+8 29=21+8消掉,我就把 8 8 8 消掉,选择 2 2 2
这时数字变成 21 21 21
对方又只能选择 [ 1 , 6 ] [1,6] [1,6], 假如他选择 6 6 6,那么 29 = 21 + 8 29=21+8 29=21+8消掉,我就把 8 8 8 消掉,选择 2 2 2
这时数字变成 21 21 21
对方又只能选择 [ 1 , 4 ] [1,4] [1,4], 假如他选择 4 4 4,那么 21 = 13 + 8 21=13+8 21=13+8消掉,我就把 8 8 8 消掉,选择 4 4 4
这时数字变成 13 13 13
对方又只能选择 [ 1 , 8 ] [1,8] [1,8], 假如他选择 8 8 8,那么 13 = 8 + 5 13=8+5 13=8+5消掉,我就把 5 5 5 直接消掉,获得胜利。

参考资料

施工进度

  • 前置知识
  • 前言
  • SG \texttt{SG} SG 函数
  • 巴什博弈 (Bash) \texttt{(Bash)} (Bash)
  • 尼姆博弈 (Nim) \texttt{(Nim)} (Nim)
  • 反尼姆博弈
  • 斐波那契博弈 (Fibonacci) \texttt{(Fibonacci)} (Fibonacci)
  • 威佐夫博弈 (Wythoff) \texttt{(Wythoff)} (Wythoff)

标签:博弈论,21,sg,texttt,基础,34,oplus,SG
From: https://blog.csdn.net/m0_73085893/article/details/141604565

相关文章

  • 运维怎么转行网络安全?零基础入门到精通,收藏这一篇就够了
    经常有人问我:干网工、干运维多年遇瓶颈,想学点新技术给自己涨涨“身价”,应该怎么选择?聪明人早已经用脚投票:近年来,越来越多运维的朋友寻找新的职业发展机会,将目光聚焦到了网络安全产业。1、为什么我建议你学习网络安全?有一种技术人才:华为阿里平安等大厂抢着要,甚至高薪难求......
  • Android网络请求 |(一) 网络基础概念
    一、前端和后端 前端和后端通过接口交互。前端web端:使用的网页,打开的网站都是前端(使用html、css等语言)显示页面以及做一些简单的校验,比如说非空校验app端:android或者object-C(开发ios上的app)开发的app,后端在页面上操作的业务逻辑、功能如:后端控制购物的时候扣除的余额,......
  • 字符串基础知识
    定义字符串对于一个字符串\(S\),\(S\)由\(n\)个字符组成,其中\(n\)是\(S\)的长度,表示为\(|S|\)。子串从一个字符串\(S\)中取出连续的一段\(T\),则\(T\)为\(S\)的子串。子序列从一个字符串\(S\)中顺序取出一些字符,组成的新的字符串就是\(S\)的子序列。前缀......
  • Linux零基础到精通(二)-vmware虚拟机使用教程及Centos7操作系统安装
    目录前言Linux操作系统运用领域vmware虚拟机安装与使用电脑硬件环境要求vmware虚拟机软件安装创建一个虚拟机配置vmware的虚拟化网络通过vmware虚拟机安装操作系统下载Centos7系统镜像安装Centos7操作系统配置网络和主机名称信息配置系统分区软件包选择设置用户密码进......
  • 用例基础知识
    •动态测试(dynamictesting):通过运行软件的组件或系统来测试软件•静态测试(statictesting):对组件的规格说明书进行评审,对静态代码进行走查=》看需求文档就属于静态测试•正式评审(formalreview):对评审过程及需求文档的一种特定评审交叉评审:测试组内测试人员互相评审对方用例......
  • 机器学习基础
    机器学习基础1机器学习基本概念机器学习的本质就是让机器具有一个找函数的能力,通过找函数能力的不同分为回归、分类、结构化学习1(1)回归假设要找的函数的输出是一个数值,一个标量,则为回归类问题,如预测类模型就是回归类问题1(2)分类分类则是让机器做出选择,人类先准备好一些选项,......
  • 【PyQt5 应用程序】PyQt基础组件:按钮
    在任何图形用户界面(GUI)应用程序中,按钮是最基本也是最频繁使用的组件之一。它们是用户与应用程序交互的主要方式之一。在PyQt中,按钮可以通过QPushButton类创建,它提供了丰富的功能,包括显示文本、图像,以及响应点击事件。本节将引导你了解如何在PyQt应用中创建和使用按钮,并通过......
  • 【python】基础之生成器
    1.什么是生成器?是Python中一种特殊的迭代器,它是一个能按需生成值的轻量级对象。与一次性创建所有元素的数据结构(如列表或元组)不同,生成器在每次迭代时只生成下一个值,从而节省内存并支持无限序列或其他大量数据流的操作。#iter中简单是4行代码,可以代替MyRangeIterator一样的......
  • 零基础5分钟上手亚马逊云科技 - AI模型内容安全过滤
    在上一篇文章中,小李哥带大家深入调研亚马逊云科技AI模型平台AmazonBedrock热门开发功能,了解了模型平台的文字/图片生成、模型表现评估和模型内容安全审核的实践操作。这次我们将继续介绍如何利用API的形式,利用Python代码的形式对AI模型内容安全过滤,阻止输入、输出中有危害的内......
  • 【python】基础之迭代器
    1.总览2.迭代器介绍2.1:迭代器是一个实现了迭代协议的对象,它可以让我们遍历一个容器中的所有元素,而不需要知道容器的内部结构,迭代器可以用于遍历列表,元祖,字典,集合等容器类型;2.2:迭代器的工作原理是通过实现两个方法:iter()和__next__()方法,iter()方法返回迭代器对象本身,next......