[数论第四节]容斥原理/博弈论/NIM游戏

这篇具有很好参考价值的文章主要介绍了[数论第四节]容斥原理/博弈论/NIM游戏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 容斥原理

    • \(|A\cup B\cup C|=|A|+|B|+|C|-|A\cap B|-|A\cap C|-|B\cap C|+|A\cap B\cap C|\)
    • \(|\displaystyle \cup_{i=1}^n A_i |=\sum_{i}|A_i|-\sum_{i,j} |A_i \cap A_j|+\ldots +(-1)^{n+1}|\cap_{i=1}^n A_i |\)
    • 时间复杂度:\(C_n^1+C_n^2+C_n^3···+C_n^n=2^n-1\) \(O(2^n-1)\)
    • 等式右边有 \(2^n-1\) 项,每一项表示选取若干个集合相交的情况,可以通过DFS遍历每种选取的情况,也可以把每种选取的情况与一个二进制数相对应
    • 该二进制数有n位,每一位表示一个集合,该位为1表示选取了该集合,为0表示不选取该集合,遍历 \(2^n-1\) 次即可遍历所有选取情况 \(O(n(2^n-1))\)
    • 代码:
      typedef long long LL;
      const int N = 20;
      int p[N];
      int n, m;
      
      int main(){
          cin >> n >> m;
          for(int i = 1; i <= m; ++ i) cin >> p[i];
          
          int res = 0; //记录答案
          for(int i = 1; i < 1 << m; ++ i){ //遍历2^m-1次,即遍历所有的方案
              int t = 1, cnt = 0; //记录当前p的倍数,以及p的个数
              for(int j = 1; j <= m; ++ j){ //遍历m位,求出当前方案选取的质数及个数
                  if(i >> (j - 1) & 1){
                      cnt ++ ; //选取了当前位的质数,质数加一
                      if((LL)t * p[j] > n){ //判断质数的倍数是否超出范围
                          t = -1;
                          break;
                      }
                      t = (LL)t * p[j]; //累乘当前位的质数
                  }
              }
              if(t != -1){
                  if(cnt % 2) res += n / t; //个数质数位奇数,则取加号
                  else res -= n / t; //否则取减号
              }
          }
          
          cout << res;
          return 0;
      }
      
  • 博弈论

    • 公平组合游戏ICG
      • 由两名玩家交替进行
      • 在游戏的任意时刻,玩家执行的合法行动与轮到哪名玩家无关
      • 不能行动的玩家判负
    • 先手必胜状态:先手行动后将当前局面变为先手必败状态,由于另一个人是下一次的先手,则另一个人必败,故先手必胜
    • 先手必败状态:先手无论怎样行动都无法将当前局面变为先手必败状态,则另一个人必胜,故先手必败
    • 普通-NIM游戏

      • \(n\) 堆石子,每堆石子个数为 \(a_i\) 颗,先手和后手每次可以从某堆中拿任意颗石子,最后无法操作的一方判负
      • 结论:当每堆石子的异或值 \(a_1 \wedge a_2 \wedge a_3 ···\wedge a_n=0\) 时 先手必败,否则先手必胜
      • 证明:
        • \(a_1 \wedge a_2 \wedge a_3 ···\wedge a_n=x\neq0\) 时 设 \(x\) 的二进制中最高位的1在第k位,那么 \(a_1···a_n\) 中至少有一个数的二进制第k位也是1,设该数为 \(a_i\)\(a_i \wedge x<a_i\) ,让先手在第i堆中取走 \(a_i-a_i \wedge x\) (一定是合法的)颗石子,第i堆还剩下 \(a_i \wedge x\) 颗石子,此时每堆石子的异或值 \(a_i \wedge a_2 \wedge a_3 ··· \wedge a_i \wedge x···\wedge a_n=x \wedge x=0\),故先手总是可以将局面变成所有石子异或值为0的情况,所以最后遇到所有石子为0的情况的一定是后手,故后手必败,先手必胜·
        • \(a_1 \wedge a_2 \wedge a_3 ···\wedge a_n=x=0\) 时 假设先手在第i堆中拿走k颗石子能将剩余石子的异或值不变,则每堆石子的异或值为 \(a_1 \wedge a_2 \wedge a_3 ···\wedge (a_i-k)···\wedge a_n=a_1 \wedge a_2 \wedge a_3 ···\wedge a_i···\wedge a_n=x=0\) 异或满足消去律,所以有 \(a_i=a_i-k\)\(k=0\) 矛盾,所以先手不可能将当前局面变成异为0的局面,故后手总是异或非0的局面,而后手总是可以将异或非0的局面变成异或为0的局面,因而先手总是会遇到异或为0的局面,最终所有石子为0的局面一定是先手遇到,故后手必胜,先手必败
    • 台阶-NIM游戏

      • 有一个 n级台阶的楼梯,每级台阶上都有若干个石子,其中第 i 级台阶上有 \(a_i\) 个石子(i ≥1)。两位玩家轮流操作,每次操作可以从任意一级台阶上拿若干个石子放到下一级台阶中(不能不拿)。已经拿到地面上的石子不能再拿,最后无法进行操作的人视为失败。
      • 结论:当奇数台阶上石子的异或值 \(a_1 \wedge a_2 \wedge a_3 ···\wedge a_n=0\) 时 先手必败,否则先手必胜
      • 石子只能从上一台阶往下一台阶拿,最终局面一定是某人把第一台阶上的石子拿到地面后结束,因此考虑奇数台阶石子异或值的情况
      • 当先手遇到奇数台阶石子异或值非0时,将某奇数台阶上的若干石子拿到下一台阶后,总是可以将所有奇数台阶上的石子异或值变成0(见普通nim游戏的分析)。此时,后手总是会遇到奇数台阶石子异或值为0的情况
      • 当后手从奇数台阶拿x石子放到下一台阶时,奇数台阶石子异或值一定变为非0(见普通nim游戏分析),此时,先手又可以将异或非0变成异或为0
      • 当后手从偶数台阶拿x石子放到下一台阶时,先手可以顺次将下一台阶的x石子放到下下一台阶,保持奇数台阶异或为0的局面,所以后手总是会遇到奇数台阶石子异或值为0的情况,直到最后,后手会遇到第一台阶无石子可拿的情况,后手判负,先手必胜
      • 当先手遇到奇数台阶石子异或值为0时,后手可以依据同样的策略使先手比败,后手必胜
    • 集合-NIM游戏

      • n堆石子,玩家可以从任意一堆石子中取走石子,但是每次取的石子个数必须在一个已知的集合S中,最后无法操作的人判负
      • 结论:当每堆石子的sg异或值 \(sg(a_1) \wedge sg(a_2) \wedge sg(a_3) ···\wedge sg(a_n)=0\) 时 先手必败,否则先手必胜
      • 集合nim与普通nim游戏的最大区别在于,拿走的石子数必须在一个给定的集合S中。
      • 对于普通nim游戏,所有石子异或非0的局面总是能够变成异或为0的局面,异或为0的局面总是只能变成异或非0的局面,故而异或为0的局面总是由同一个人遇到,异或非0的局面总是让另一个人遇到,因此一开始通过石子的异或值就能确定谁是赢家。
      • 对于集合nim游戏,是否有同一个局面只会让同一个人遇到的情况呢?答案是可以的。将每种局面抽象为一个图中的节点,一个局面可以到另一种局面就连一条有向边,因而每堆石头的取法都可以通过一个图表示,出度为0的节点表示结束局面
      • 定义一个sg(x)函数,表示局面x的sg值,该值总是取到达不了的局面中的最小值,结束局面的sg值为0,能到结束局面的局面的值为1,同理,可以反推出每堆石头一开始的sg值
      • 可以发现该sg值与普通nim游戏中异或值的情况有相似之处,即sg值为0的局面只能走到sg值非0的局面,sg值非0的局面总是可以走到sg值为0的局面
      • 将每堆石头起始节点的sg值异或起来,sg异或值为0则先手比败,sg异或值非0则先手必胜(sg异或值为0的那一方总是遇到sg值异或值为0)
      • 代码:
        #include <iostream>
        #include <unordered_set>
        #include <cstring>
        
        
        using namespace std;
        
        const int N = 110;
        const int M = 1e4 + 10;
        int s[N], f[M]; //s[i]存储可以取的石子数,f[i]存储每个状态的sg值,每个状态用当前石子数表示
        int n, k;
        
        //dfs求sg值
        int sg(int x){
            if(f[x] != -1) return f[x]; //记忆化搜索
            
            unordered_set<int> S; //储存可以走到的局面的sg值
            for(int i = 1; i <= k; ++ i){ //遍历所有可以取的石子数量
                int sum = s[i];
                if(x >= sum) S.insert(sg(x - sum)); //将走到的局面的sg值存储
            }
            
            for(int i = 0; ; ++ i) //从小到大遍历可能的sg值
                if(!S.count(i)) //若该sg值是不能达到的sg中的最小值
                    return f[x] = i; //取该sg值
        }
        
        int main(){
            cin >> k;
            for(int i = 1; i <= k; ++ i) cin >> s[i];
            cin >> n;
            
            memset(f, -1, sizeof f);//别忘了初始化
            
            int res = 0;
            while(n -- ){
                int h;
                cin >> h;
                res = res ^ sg(h); //起点的sg异或值
            }
            
            if(res) cout << "Yes";
            else cout << "No";
            return 0;
        }
        
    • 拆分-NIM游戏

      • 给定 n堆石子,两位玩家轮流操作,每次操作可以取走其中的一堆石子,然后放入两堆规模更小的石子(新堆规模可以为 0,且两个新堆的石子总数可以大于取走的那堆石子数),最后无法进行操作的人视为失败。
      • 结论:==当每堆石子的sg异或值 \(sg(a_1) \wedge sg(a_2) \wedge sg(a_3) ···\wedge sg(a_n)=0\) 时 先手必败,否则先手必胜
      • 补充sg定理:SG 定理适用于 任何公平的两人游戏, 它常被用于决定游戏的输赢结果。计算给定状态的 Grundy 值的步骤一般包括:
        • 获取从此状态所有可能的转换;
        • 每个转换都可以导致 一系列独立的博弈(退化情况下只有一个)。计算每个独立博弈的 Grundy 值并对它们进行 异或求和
        • 在为每个转换计算了 Grundy 值之后,状态的值是这些数字的mex
        • 如果该值为零,则当前状态为输,否则为赢。
      • 由于玩家的操作是拿走一堆石子,放入两堆石子,因此原来一堆石子的局面变成了两堆石子的局面,而这两堆石头是同时出现,所以尽管是两堆石头,但是属于一个局面,由sg定理此局面的sg值 为 sg(x) = sg(x1) ^ sg(x2) (x -> x1 + x2 拿走x,放入x1,x2)
      • 代码:
        #include <iostream>
        #include <cstring>
        #include <unordered_set>
        
        using namespace std;
        
        const int N = 110;
        int f[N];
        int n;
        
        int sg(int x){
            if(f[x] != -1) return f[x];//记忆化
            
            unordered_set<int> s;
            for(int i = 0; i < x; ++ i) 
                for(int j = 0; j <= i; ++ j) //避免重复,约定第二堆的数量小于等于第一堆
                    s.insert(sg(i) ^ sg(j)); //两个石子为一个局面,由sg定理:两个石子的sg异或值为当前局面的sg值
                    
            for(int i = 0; ; ++ i) //选取不存在的最小的自然数
                if(!s.count(i))
                    return f[x] = i;            
        }
        
        int main(){
            cin >> n;
            memset(f, -1, sizeof f);
            int res = 0;
            while(n -- ){
                int x;
                cin >> x;
                res ^= sg(x);
            }
            
            if(res) cout << "Yes";
            else cout << "No";
            return 0;
        }
        

文章来源地址https://www.toymoban.com/news/detail-645195.html

到了这里,关于[数论第四节]容斥原理/博弈论/NIM游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【博弈论】【第一章】博弈论导论

    课程概述: 两个参与人A和B,轮流选择[3,4,5,6,7,8,9]中的一个整数(可重复)。当累计总和达到100的时候,博弈结束。此时判所选数字恰好使累计总和达到或超过100的参与人为输家。试问最先行动的A能赢得这场博弈吗?最优策略又是什么? 【解】 整个游戏的过程: 如果前面选择的

    2024年02月03日
    浏览(46)
  • 汤姆·齐格弗里德《纳什均衡与博弈论》笔记(4)博弈论与人性

    第五章 弗洛伊德的梦——博弈和大脑 大脑和经济学 曾经有一段时间——就像在弗洛伊德的年代——心理学家们无法准确地回答人类行为背后的大脑机制。但随着现代神经科学的兴起,情形改变了。比如,人类的情绪不再像过去一样是个谜。科学家们可以观察当人们感到轻蔑

    2024年01月25日
    浏览(54)
  • 【学习笔记】博弈论 ---- 非偏博弈

    本篇按照 Qingyu 在省集讲的加入我这个萌新的萌新理解而成。 听了 Qingyu 的博弈论讲解,感觉我之前学过的博弈就是冰山一角。 由于有一些东西没听懂,就主要写写我听懂的部分,没懂得以后再说吧。 所以这篇只是一个入门,关于博弈的一些习题可能会咕咕咕。 几个基本定

    2024年02月07日
    浏览(56)
  • 博弈论 | 斐波那契博弈

    博弈论是二人或多人在平等的对局中各自利用对方的策略变换自己的对抗策略,达到取胜目标的理论。博弈论是研究互动决策的理论。博弈可以分析自己与对手的利弊关系,从而确立自己在博弈中的优势,因此有不少博弈理论,可以帮助对弈者分析局势,从而采取相应策略,最终达到

    2024年02月12日
    浏览(43)
  • 汤姆·齐格弗里德《纳什均衡与博弈论》笔记(7)博弈论与概率论

    第十一章 帕斯卡的赌注——博弈、概率、信息与无知 在与费马就这个问题的通信过程中,帕斯卡创造出了概率论。另外,帕斯卡在进行严谨的宗教反思中,得出了 概率 这个概念,它在此几百年后,成为一个关键的、对博弈论的提出有重要意义的数学概念。 帕斯卡观察到,

    2024年01月25日
    浏览(52)
  • 博弈论-策略式博弈矩阵、扩展式博弈树 习题 [HBU]

    目录 前言: 题目与求解 11.请将“田忌赛马”的博弈过程用策略式(博弈矩阵)和扩展式(博弈树)分别进行表示,并用文字分别详细表述。 34.两个朋友在一起划拳喝酒,每个人有4个纯策略:杠子、老虎、鸡和虫子。 输赢规则是:杠子降老虎,老虎降鸡,鸡降虫子,虫子降

    2024年02月03日
    浏览(49)
  • 【博弈论笔记】第二章 完全信息静态博弈

    此部分博弈论笔记参考自经济博弈论(第四版)/谢识予和老师的PPT,是在平时学习中以及期末备考中整理的,主要注重对本章节知识点的梳理以及重点知识的理解,细节和逻辑部分还不是很完善,可能不太适合初学者阅读(看书应该会理解的更明白O(∩_∩)O哈哈~)。现更新到

    2024年02月10日
    浏览(51)
  • 博弈论入门

    古诺双寡头模型的条件 市场中有且仅有两家公司 策略为同质商品的量, q i q_i q i ​ 边际成本为c,生产成本就为c*q,在这里我们的边际成本是常数。 需求曲线: P = a − b ∗ ( q 1 + q 2 ) P=a-b*(q_1+q_2) P = a − b ∗ ( q 1 ​ + q 2 ​ ) 利润: U 1 ( q 1 , q 2 ) = P ∗ q 1 − c ∗ q 1 , U 2 (

    2024年02月02日
    浏览(44)
  • 博弈论算法常见模型整理

    本文主要介绍算法竞赛中常常出现的博弈论模型,包括: 4个经典组合游戏 SG函数 SG游戏及拓展 进一步学习需要了解一些前置概念 ICG 博弈图 P点、N点 mex函数 1.ICG ICG全称为“公平组合游戏”,我们下面讨论的博弈游戏均建立在ICG的基础上,那么什么是ICG呢,它需要满足以下条

    2023年04月26日
    浏览(43)
  • 博弈论小课堂:零和博弈(找到双方的平衡点)

    从概率论延伸出来的课题——博弈论,博弈论中最典型的两大类博弈,是“零和博弈”与“非零和博弈”。博弈论所研究的最优化问题有多方参与,因此最优化的策略要考虑对方的行为。 博弈论通常被认为是冯·诺依曼发明的,博弈论从本质上讲,是一套解决最优化问题的方

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包