第四章 数学知识(四)——容斥原理与博弈论

news2024/11/27 2:45:37

文章目录

    • 容斥原理
    • 博弈论
      • SG函数
    • 容斥原理练习题
      • 890. 能被整除的数
    • 博弈论练习题
      • 891. Nim游戏
      • 893. 集合-Nim游戏
      • 892. 台阶-Nim游戏
      • 894. 拆分-Nim游戏

容斥原理

若干个相交集合,它们的并集中存在多少个元素?
假设n为所有集合的元素个数相加,因为集合间存在交集,所以n中有重复计算
比如三个集合 A , B , C A,B,C ABC
∣ A ∪ B ∪ C ∣ = ∣ A ∣ + ∣ B ∣ + ∣ C ∣ − ∣ A ∩ B ∣ − ∣ A ∩ C ∣ − ∣ B ∩ C ∣ + ∣ A ∩ B ∩ C ∣ |A∪B∪C| = |A| + |B| + |C| - |A∩B| - |A∩C| - |B∩C| + |A∩B∩C| ABC=A+B+CABACBC+ABC
推广到n个集合,并集的元素个数 = 每个集合的元素个数相加 - 任意两个集合的交集元素个数 + 任意三个集合的交集元素个数 - …
为什么要这样的重复?因为式子的每一项都有重复操作,如:每个集合的元素个数相加,因为任意两个集合间可能存在交集,所以有些元素被二次增加
减去这些被二次增加的元素,因为任意三个集合间可能存在交集,所以有些元素被二次删除
加上这些被二次删除的元素,可以发现每个操作都在弥补上次操作的重复
何时停止?加上或减去所有集合的交集时停止

那么推广公式中有多少项?
观察所有项,有些项是一个集合的交集(本身)元素个数,有些项是两个,有些是三个,最多到n个。所以这是个组合问题,从n个集合中选择k个集合,k从1~n,将这些组合数相加就是项数
image.png
根据等式:
∑ k = 0 n C n k = 2 n \sum_{k=0}^{n}C_n^k=2^n k=0nCnk=2n
所以推得:项数 = 2 n 2^n 2n - 1

容斥原理证明:
假设在 n n n个集合中,数 x x x属于 k k k个不同的集合,在容斥原理的展开式中 x x x的出现次数为(蓝字):
image.png
列出该表达式,根据等式:
∑ i = 1 k ( − 1 ) i − 1 C k i = 1 \sum_{i = 1}^{k}(-1)^{i-1}C_k^i=1 i=1k(1)i1Cki=1
所以在容斥原理的展开式中, x x x的出现次数为1,即在所有集合的并集中, x x x只出现一次
x x x推广为集合中的任意元素,即证:容斥原理成立


博弈论

先手不是指第一出手方,而是指下一出手方
必胜态:可以走到(下一回动手)先手必败态
必败态:走不到先手必败态,不论怎么走都将走到先手必胜态

问题:
image.png

假设n堆石子的数量为 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an,若a_1 ^ a_2 ^ ... ^ a_n = 0,则先手必败
否则先手必胜

分析:

  1. 不能进行任何操作(所有堆的石子为0),异或结果为0
  2. 异或结果不是0,一定可以通过某种方式使得异或结果为0

当异或结果非0时,一定有方法使得拿走石子后,异或结果为0
证明:
当异或结果为x(非0),x的二进制表示中,最高的一位1在第k位
其他数中必然存在至少一个数 a i a_i ai,其第k位为1
那么就有 a i a_i ai ^ x < a i a_i ai a i a_i ai ^ x 后,第k为从1变为0,结果减小
从堆中拿走( a i a_i ai - a i a_i ai ^ x)的石子,那么堆中剩下的石子数量为 a i a_i ai-( a i a_i ai - a i a_i ai ^ x)=( a i a_i ai ^ x)
此时将所有堆的石子数量进行异或,结果为0,因为只有 a i a_i ai变为了 a i a_i ai ^ x
其中x为 a i a_i ai变化之前的异或结果, a i a_i ai变化后,异或结果为x ^ x = 0

异或结果为0时,无论怎么拿,之后的异或结果一定不是0
证明:反证
假设从 a i a_i ai中拿走石子,剩下 a i ′ a_i' ai的石子,若此时的异或结果为0,将此时的异或等式与之前的异或等式进行异或
那么除了 a i a_i ai a i ′ a_i' ai剩下的项都是相同的,因为异或结果为0,所以 a i a_i ai ^ a i ′ a_i' ai = 0
说明 a i a_i ai = a i ′ a_i' ai,也就是没有拿走石子,与前提 a i ′ a_i' ai < a i a_i ai矛盾
所以若异或等式为0,那么无论此时怎么拿,异或结果不是0

因此,若双方都尽力在赢,那么双方就能使异或结果非0的局面转换到异或结果为0,也能使异或结果为0的局面转换为非0
当没有石子剩下,此时异或结果为0
所以,先手方的局面中,异或结果为0,那么先手必败。反之,先手必胜


SG函数

若题目不再允许每次拿走任意石子,而限定每次拿走的石子数量时
以上结论依然有效,只不过用来做异或运算的不再是每堆石子的数量,而是SG值:
先手时,SG(x) == 0为必败态,SG(x) != 0为必胜态
将n堆石子能进行的所有局面看成一张图,将每张图中起点SG的值异或,结果为0必败,否则必胜

如何计算SG值?
每进行一个操作都能从一个局面转移到另一个局面,用点表示局面,对于初始状态的所有可能操作就组成了一张有向图

若一个点没有出边,那么该点就被定义为终点,SG(终点) = 0
对于当前点,也就是,当前局面x,若其能转移成 y 1 y_1 y1, y 2 y_2 y2, …, y k y_k yk局面,那么:
SG(x) = Mex(SG( y 1 y_1 y1), SG( y 2 y_2 y2), … , SG( y k y_k yk))
定义Mex运算,找到一个集合中不存在的最小的非负整数,也就是说在集合中,小于该数的所有非负整数是存在且连续的
也就是说,若SG(x) = n,那么从当前局面x一定能够转移到SG值小于n的任意局面

给定一个初始集合,即已知起点局面,此时如何知道其他局面?即如何推导有向图中其他点的SG值?
和扩展欧的递归求系数类似,我们需要递归到不能递归为止,以找到了终点,由于已知终点的SG值为0,所以此时可以更新终点
通过终点的SG值倒推其他点的SG值:若一点只能通向终点,那么该点的SG值为1
推广:若已知一点连通的其他点,我们需要从0开始枚举这些点的SG值,找一个不存在且最小的值,作为当前点的SG值
出边连通的点的SG值用set存储,这样就不用排序了

用石子的数量表示图中的一个唯一点,用其查询该点的SG值
如下图,若某个石子堆中出现了剩余石子数量相同的局面(两个剩余石子数量为3的局面),因为之后能转移的局面是相同的,所以这两个局面可以合并,作为图中的一个唯一点(对于不同的石子堆也是如此)
由此可知,一张图中可能存在多个相同的点(石子数量相同的局面),为防止重复查询降低效率,这里使用记忆化搜索。用数组f记录剩余石子数量为i时,该局面的SG值

image.png

模板:

int cnt[M]; // 每次能拿走的石子数量(能进行的操作)
int f[N];
memset(f, -1, sizeof(f));
int sg(int x) // x为堆中剩余的石子数量,函数返回该点的SG值
{
	if (f[x] != -1) return f[x];

	unordered_set<int> s; // 当前点的出边连通的点的SG值
	for (int i = 0; i < m; ++ i ) // m为堆的数量
		if (x >= cnt[i]) s.insert(sg(x - cnt[i])) ;
	for (int i = 0; ; i ++ )
		if (!s.count(i)) return f[x] = i;
}

为什么能从0->!0,!0->0?证明的思路和原题一样,
!0->0:
异或结果为x时,因为Mex的存在, a i a_i ai一定能变化成 a i a_i ai ^ x,因为 a i a_i ai ^ x < a i a_i ai
0->!0:
用反证法,证明过程与原题相同


容斥原理练习题

890. 能被整除的数

890. 能被整除的数 - AcWing题库
image.png

暴力做法:判断1~n中的每个数是否能被质数整除,最坏的情况每个数要判断m次,总共nm次

容斥原理:
每个集合定义为:在1~n中,质数 p i p_i pi的倍数的个数(能被 p i p_i pi整除的数的个数),用下取整 [ n / p i ] [n/p_i] [n/pi]即可求得
问题转换成了:求这些集合的并集中元素的个数

首先,容斥原理展开式有 2 n 2^n 2n-1项, n n n为集合的数量
因为题目给定的质数个数最为16,也就是 n n n最多为16
对于展开式中的某一项,我们可以直接对一个数的第 i i i位进行位运算判断第 i i i集合是否在该项中(作为并集的一部分)
由于每一项至少要选择一个集合,所以数从1开始
若该项有奇数个集合,加上该项,否则减去该项

#include <iostream>
using namespace std;

typedef long long LL;
const int N = 20;
int p[N];
int n, m;

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++ i ) scanf("%d", &p[i]);
    int res = 0;
    for (int i = 1; i < 1 << m; ++ i )
    {
        int t = 1, s = 0; // t为分母,s为分母中集合的个数
        for (int j = 0; j < m; ++ j )
        {
            if ((i >> j) & 1)
            {
                if ((LL)t * p[j] > n)
                {
                    s = -1;
                    break;
                }
                t = (LL)t * p[j];
                s ++ ;
            }
        }
        if (s == -1) continue;
        if (s % 2) res += n / t;
        else res -= n / t;
    }
    printf("%d\n", res);
    
    return 0;
}

博弈论练习题

891. Nim游戏

891. Nim游戏 - AcWing题库
image.png

#include <iostream>
using namespace std;

int main()
{
    int n;
    scanf("%d", &n);
    int res = 0, x;
    while (n -- )
    {
        scanf("%d", &x);
        res ^= x;
    }
    
    if (res) puts("Yes");
    else puts("No");
    
    return 0;
}

893. 集合-Nim游戏

893. 集合-Nim游戏 - AcWing题库
image.png

#include <iostream>
#include <cstring>
#include <unordered_set>
using namespace std;

const int K = 110, M = 10010;
int cnt[K], f[M];
int k, n;

int sg(int x)
{
    if (f[x] != -1) return f[x];
    unordered_set<int> s;
    for (int i = 0; i < k; ++ i )
        if (x >= cnt[i]) s.insert(sg(x - cnt[i]));
        
    for (int i = 0; ; ++ i )
        if (!s.count(i)) return f[x] = i;
}

int main()
{
    scanf("%d", &k);
    for (int i = 0; i < k; ++ i ) scanf("%d", &cnt[i]);
    
    scanf("%d", &n);
    memset(f, -1, sizeof(f));
    int x, res = 0;
    while (n -- )
    {
        scanf("%d", &x);
        res ^= sg(x);
    }
    
    if (res) puts("Yes");
    else puts("No");
    
    return 0;
}

892. 台阶-Nim游戏

892. 台阶-Nim游戏 - AcWing题库
image.png

将所有奇数台阶看成经典Nim游戏即可
当所有奇数台阶的石子异或结果为0,先手必败。反之先手必胜
证明:
必败的局面为:所有奇数台阶的石子不为0,偶数台阶的石子为0,此时只能从奇数台阶拿石子到偶数台阶,但是对方能拿走你拿下的石子。也就是对方始终能保证偶数台阶的石子为0,并且自己的局面中,一定有奇数台阶的石子不为0
最后的情况为:1号台阶的石子不为0,其他台阶的石子为0,此时先手方必胜

推广一下,保证所有奇数台阶的石子数量异或结果为0,那么一定能递达一个局面,即所有奇数台阶的石子数量为0。此时先手必败

对于所有奇数台阶的石子异或结果为0的局面,先手方:

  1. 从偶数台阶拿下石子,后手方拿走先手方拿下的石子即可,将变化的奇数台阶数量恢复
  2. 从奇数台阶拿下石子,后手方一定能从某个奇数台阶拿走石子,使得奇数台阶的石子数量异或结果为0。这是经典的Nim游戏
#include <iostream>
using namespace std;

int main()
{
    int n, x, res = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i )
    {
        scanf("%d", &x);
        if (i % 2) res ^= x;
    }
    if (res) puts("Yes");
    else puts("No");
    
    return 0;
}

894. 拆分-Nim游戏

894. 拆分-Nim游戏 - AcWing题库
image.png

#include <iostream>
#include <unordered_set>
#include <cstring>
using namespace std;

const int N = 110;
int n, f[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));
    for (int i = 0; ; ++ i )
        if (!s.count(i))
            return f[x] = i;
}

int main()
{
    memset(f, -1, sizeof(f));
    scanf("%d", &n);
    int res = 0, x;
    while (n -- )
    {
        scanf("%d", &x);
        res ^= sg(x);
    }
    
    if (res) puts("Yes");
    else puts("No");
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue img 图片损坏时展示替图片

场景&#xff1a;图片地址找不到时&#xff0c;会展示如图一&#xff1b;虽然没什么大影响&#xff0c;但是有点丑&#xff0c;需求是想在图片损坏时展示替补图片&#xff0c;如图二。 代码实现&#xff1a;给img标签加error事件 <img :src"item.imageUrl" :alt&q…

android JSBridge的加载时机问题

https://github.com/lzyzsd/JsBridge 也算是比较悠久和使用了。 可供参考的android和IOS&#xff0c;以及前端的使用 https://segmentfault.com/a/1190000018208609 遇到的问题&#xff1a; 比如&#xff1a; 从前端在加载WebView的时候&#xff0c;执行了某些动作&#xff0c…

【Java/大数据】Kafka简介

Kafka简介 Kafka概念关键功能应用场景 Kafka的原理Kafka 的消息模型早期的队列模型发布-订阅模型Producer、Consumer、Broker、Topic、PartitionPartitionoffsetISR Consumer Groupleader选举Controller leaderPartition leader producer 的写入流程 多副本机制replicas的同步时…

介绍AI绘画课,让智能工具助力创作 释放无限想象力 助你成为绘画大师

演示地址&#xff1a; www.runruncode.com/portal/article/index/id/19458/cid/81.html 画画是一项有趣的活动&#xff0c;它让人充满无限可能。对许多人来说&#xff0c;画画既是一种放松的方式&#xff0c;也是一种与创意、文化和艺术联系的途径。如果你是一个初学者&#x…

《深度学习推荐系统》笔记

目录 一、推荐系统是什么1.作用和意义2.推荐系统的架构2.1 逻辑架构2.2 技术架构 二、传统的推荐系统方法1. 协同过滤算法1.1 userCF&&ItemCF1.3 矩阵分解算法 2. 逻辑回归算法3. 因子分解机3.1 POLY2模型3.2 FM模型3.3 FFM模型3.4 小结 4. 组合模型4.1 GBDTLR组合模型…

valle代码过程

github代码链接 https://github.com/lifeiteng/vall-e/tree/main1.PyTorch pytorch官网 https://pytorch.org/指令 conda install pytorch torchvision torchaudio pytorch-cuda11.8 -c pytorch -c nvidiapip install torchmetrics0.11.12.fbank pip install librosa0.8.1…

前端vue入门(纯代码)33_缓存路由组件

如果我一贫如洗&#xff0c;你将会是我最后一件行李。 【31.Vue Router--缓存路由组件】 背景&#xff1a;在Cartoon组件的input框&#xff0c;输入了一些数据的时候&#xff0c;但是&#xff0c;当我切换到Stars组件的时候&#xff0c;那么Cartoon组件就会被销毁&#xff0c…

易基因“多区域DNA甲基化检测探针设计及其检测方法”获专利授权!

大家好&#xff0c;这里是专注表观组学十余年领跑多组学科研服务的易基因。 DNA甲基化是表观遗传学研究中&#xff0c;修饰最为稳定&#xff0c;含量最为丰富&#xff0c;对基因调控最为活跃、途径最为广泛的一种修饰。不同基因区域或位点的修饰与胚胎发育、疾病发生和发展密切…

三层架构详解

什么是三层架构&#xff1f; 三层架构就是为了符合“高内聚&#xff0c;低耦合”思想&#xff0c;是一种十分完善的软件应用程序架构&#xff0c;它将应用程序组织成三个逻辑和物理计算层&#xff1a;表示层&#xff08;或用户界面&#xff09;、应用层&#xff08;负责处理数据…

Java中abstract关键字

文章目录 由来语法格式使用说明应用举例 由来 举例1&#xff1a; 随着继承层次中一个个新子类的定义&#xff0c;类变得越来越具体&#xff0c;而父类则更一般&#xff0c;更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象&#xff0c;以至于它…

数字赋能,你见过哪些科技感爆棚的VR数字展厅呢?

随着科技的不断进步&#xff0c;线上展厅作为一种新型的展示方式&#xff0c;在社会层面得到了广泛的认可和应用&#xff0c;VR数字展厅带给观众不一样的视觉震撼感&#xff0c;大大提升了品牌的价值。 传统的功能性展馆或是展厅千篇一律&#xff0c;缺乏品牌特色以及趣味性&am…

springboot之配置文件加载

springboot启动流程参考。Springboot总结。本内容主要解析里面的配置文件的加载过程。 springboot资源加载 入口。SpringApplication#run 我们知道&#xff0c;run方法是构建容器的过程。里面有一个方法&#xff1a;prepareEnvironment。用于构建环境组件Environment&#xf…

【ArcGIS Pro二次开发】(48):三调土地利用现状分类面积汇总统计

之前做了一个三调三大类面积统计&#xff0c;有小伙伴反映太粗糙&#xff0c;想要一个完整的地类面积汇总表。 【ArcGIS Pro二次开发】(35)&#xff1a;三调三大类面积统计 本质上并没有多少难度&#xff0c;之前也做过类似的用地用海汇总表&#xff0c;于是拿出来改一改就好了…

3D开发工具HOOPS 2023 SP2更新:增加了SOLIDWORKS贴花支持!

HOOPS SDK是全球领先开发商TechSoft 3D旗下的原生产品&#xff0c;专注于Web端、桌面端、移动端3D工程应用程序的开发。长期以来&#xff0c;HOOPS通过卓越的3D技术&#xff0c;帮助全球600多家知名客户推动3D软件创新&#xff0c;这些客户包括SolidWorks、SIEMENS、Oracle、Ar…

几款好用软件,嗐,朋友推荐的,真香

1、git加速 官网&#xff1a;https://steampp.net/ 2、gif 截图 官网&#xff1a;https://www.screentogif.com/

scss 预处理器自定义ui框架(bem架构)

BEM架构 bem架构 它是一种css架构 oocss 实现的一种 &#xff08;面向对象css&#xff09; &#xff0c;BEM实际上是block、element、modifier的缩写&#xff0c;分别为块层、元素层、修饰符层&#xff0c;element UI 也使用的是这种架构 BEM 命名约定的模式是&#xff1a; …

kaggle,球员接触检测

比赛链接 比赛目标 检测球员在NFL橄榄球比赛中所经历的外部接触。你将使用视频和球员跟踪数据来识别与接触的时刻&#xff0c;以帮助提高球员的安全。 评价指标 马修斯相关系数&#xff08;Matthews Correlation Coefficient&#xff0c;简称MCC&#xff09;是一种常用的二…

图论算法笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 第12章 最短路径算法12-1 有权图的最短路径问题最短路径问题-路径规划单源最短路径带权图的最短路径和无权图的最短路径带权图的最短路径算法-Dijkstra算法 12-2 Di…

检测到目标Strict-Transport-Security响应头缺失

详细描述 Web 服务器对于 HTTP 请求的响应头中缺少 Strict-Transport-Security&#xff0c;这将导致浏览器提供的安全特性失效。 当 Web 服务器的 HTTP 头中包含 Strict-Transport-Security 头时&#xff0c;浏览器将持续使用 HTTPS 来访问 Web 站点&#xff0c;可以用来对抗协…

Echart柱形图条纹设置

代码内容: option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [120, 200, 150, 80, 70, 110, 130],type: bar},{data: [20, 40, 90, 40, 30, 70, 120],type: bar},{data: [140, 230, 120, 50, 30, 150, 120]…