容斥基础

news/2025/3/20 20:44:05/文章来源:https://www.cnblogs.com/Ydoc770/p/18782370

容斥

容斥不仅有着各式各样的式子,还有正难则反,容斥的思想等重要的方法手段,是计数中非常核心的技术。

朴素容斥

朴素容斥就是最基本的在小学就学过的集合的容斥。

容斥原理

设每个元素有 \(n\) 个可能的属性 \(p_i\) 表示其属于第 \(i\) 个集合 \(S_i\),那么对于所有集合的并集,我们有

\[\left| \bigcup_{i=1}^n S_i\right|= \sum_{x=1}^n(-1)^{x-1}\sum_{i_1<i_2<\cdots<i_x}\left|\bigcap_{j=1}^xS_{i_j} \right| \]

也就是说我们赋予集合一个顺序之后,如果我们知道所有 \(1\) 个、\(2\) 个、\(\cdots\)\(n\) 个元素的集合的交集大小,我们就可以求出这 \(n\) 个集合的并集大小。这就是朴素的容斥原理的式子。

注意这里的 \((-1)^{x-1}\) 也被称为容斥系数,也就是在容斥中让你要求的东西的系数为 \(1\) 或者一个常数的一个函数。下面我们将证明 \((-1)^{x-1}\) 是让每个元素统计贡献为 \(1\) 的容斥系数。

证明

我们考虑某个元素出现在 \(m\) 个集合 \(T_1,T2,\cdots,T_m\) 中,则这个元素被统计的次数 \(cnt\) 我们就可以用上式算出。
具体地,在每次拿 \(x\) 个集合来求并集时,由于集合被赋予了顺序,所以统计到的贡献就为 \((-1)^{x-1}{m\choose x}\),即选到的 \(x\) 个集合都在这 \(m\) 个中。所以我们有

\[cnt=\sum_{x=1}^m{(-1)^{x-1}}{m\choose x} \]

凑二项式定理可以化简,得到

\[\begin{aligned} cnt&=\sum_{x=0}^m(-1)^{x-1}{m\choose x}+1\\ &=(-1)^{m+1}\sum_{x=0}^m(-1)^x{m\choose x}+1\\ &=(-1)^{m+1}(1-1)^m+1\\ &=0+1=1 \end{aligned} \]

每个元素都只统计了一次,所以最后的总贡献就是并集的元素个数。

应用

Luogu P3214 卡农

在集合 \(S=\{1,2,\cdots,n\}\) 中选择 \(m\) 个无序互异非空子集,使得每个元素被选择的次数都为偶数,求方案数。

直接考虑无序有些困难,我们先考虑有序且符合其它限制的方案数。
注意到奇偶性的限制非常弱,实际上只用拿一个子集出来,根据其他元素被选择次数的奇偶性来调整这个子集里的元素。这个子集是唯一确定的。其它非空互异的子集在 \(2^n-1\) 个非空子集中选择,有

\[(2^n-1)^{\underline{i-1}} \]

\(f_i\) 表示选择 \(i\) 个互异非空子集且每个元素被选择的次数都为偶数的方案数,答案即 \(f_m\)。容易得到 \(f_1=f_2=0\),接下来我们考虑 DP 出 \(f_i\)

在上式的基础上,我们要考虑用以调整奇偶性的子集是否合法:如果前 \(i-1\) 个子集每个元素出现次数已经是偶数,这个子集为空不合法,那么就要减去这不合法的方案数 \(f_{i-1}\);如果这个子集与之前某个子集相同,那除开这 \(2\) 个集合,剩下 \(i-2\) 个子集构成了合法方案数即 \(f_{i-2}\),先前的子集都有可能与其相同,就有 \(i-1\) 种情况,但是这两个子集与其他子集都不相同,可能的集合就有 \(2^n-1-(i-2)\) 种。这两部分非法方案都减去就得到了合法的 \(f_i\),有

\[f_i=(2^n-1)^{\underline{i-1}}-f_{i-1}-f_{i-2}\times(i-1)\times(2^n-1-(i-2)) \]

递推求出 \(f_m\),求个逆元除以 \(m!\) 转成无序的即可。

代码实现
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const int maxn = 1e6 + 10, mo = 1e8 + 7;
int n, m, f[maxn];
ll fall_fac[maxn];ll qpow(ll x, ll y) {ll res = 1;while(y) {if(y & 1) (res *= x) %= mo;(x *= x) %= mo, y >>= 1;}return res; 
}int main() {ios :: sync_with_stdio(false); cin.tie(0); cout.tie(0);cin >> n >> m; ll pow2 = qpow(2, n), fac = 1; f[0] = 1, fall_fac[1] = pow2 - 1;for(int i = 2; i <= m; i++) fall_fac[i] = fall_fac[i - 1] * (pow2 - i) % mo;for(int i = 2; i <= m; i++) { f[i] = (fall_fac[i - 1] - f[i - 1] - (i - 1) * (pow2 - 1 - (i - 2)) % mo * f[i - 2] % mo) % mo; (f[i] += mo) %= mo;}for(int i = 2; i <= m; i++) (fac *= i) %= mo;cout << 1ll * f[m] * qpow(fac, mo - 2) % mo << endl;return 0;
} 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第五周第四天

所用时间:180分钟 代码量(行):15 博客量(篇):1 了解到的知识点: 1.matplotlib的配置 因为要参加数学建模大赛,今天配置了python和matplotlib环境,尝试运行了程序,代码如下: import matplotlib.pyplot as plt import numpy as np# 生成数据 x = np.linspace(0, 10, …

Vue3中使用TinyMce编辑器

Vue3中使用TinyMce编辑器 - 知乎 一,安装TinyMce富文本vue npm install @tinymce/tinymce-vue -S npm install tinymce -STinyMce本身是英文编辑器,所以还需要下载中文本地化文件:https://www.tiny.cloud/get-tiny/language-packages/下载完成后放入node_modules下的tinymce…

入门Dify平台:如何根据需求选择与创建最合适的应用

今天我们将继续深入讲解Dify,重点介绍如何创建应用。具体来说,我们将探讨如何根据不同的需求来决定选择什么类型的应用最为合适,帮助大家更好地理解在Dify平台上构建应用的最佳实践。 创建空白应用 首先,我们需要进入Dify的首页选择工作室,并创建空白应用。如图所示:点击…

月暗推出音频模型 AudioX:任意内容生成音频和配乐;开源 TTS 模型 Orpheus,可生成叹息、笑声等非文本线索丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

202110211215 - IT项目管理笔记

IT项目管理中的百慕大 资源 、范围、进度 三角平衡 项目管理 -- 做事 启动、规划、执行、控制、收尾 项目管理 -- 四个层次: 复杂的事情简单化:分解 简单的事情量化:临界值 量化的事情专业化:规律 专业的事情模板化:框架模板 项目: 为创造特定产品或服务的一项有时限的任…

k8s拉取私有镜像的2种方式

k8s 在拉取私有镜像时 ,传递认证信息目录通过secret通过ServiceAccount 通过secret01-image-pull.yamlkind: Pod apiVersion: v1 metadata:name: imagepull-nginxlabels:group: imagepull spec:containers:- name: nginximage: registry.cn-beijing.aliyuncs.com/hkui_dev/ngi…

202110111235 - 软件工程笔记

1. 概述 1.1 开发只占冰山一角 1.2 计算机科学、数学,工程,管理 1.3 软件开发的本质:实现问题域中的概念和处理逻辑 到 运行平台的概念和处理逻辑的映射。系统建模 需求 -> 设计 -> 实现1.4 软件工程的目标:生产具有正确性、可用性、以及开销合宜的产品。 1.5 软件工…

202109060657 - hadoop架构和读写流程

1. 整体架构 hdfs架构zkmonode高可用。HA的工作原理?是否需要每个datanode监听zk?namenodeNameNode(nn):Hdfs集群的管理者,Master 管理Hdfs的名称空间(NameSpace) 维护副本策略 记录文件块(Block)的映射信息 负责处理客户端读写请求datanodeDataNode:NameNode下达命令,…

基于风险的完整性和检查建模(RBIIM)MATLAB仿真

1.程序功能描述 基于风险的完整性和检查建模(Risk-Based Integrity and Inspection Modeling ,RBIIM)MATLAB仿真,对比prior density,posterior perfect inspection,posterior imp inpection,cummulative posterior imperfect inspection四个指标。 2.测试软件版本以及…

202108151156 - kafka消费积压案例

0. 背景 上游厂家生产信令数据,我方消费kafka数据,过滤后插入HBase。 上游生产的信令数据分了4个主题,每个主题有若干分区,这4个主题的数据消费后都插入同一张HBase表。 问题:kafka消息积压达到百亿。 以下以topic1为例,有6个分区。 1. 查看消费滞后情况 kafka-consumer-…

mysql 多表怎么连接的

前言 简单描述一下多表怎么连接的。 正文 首先,我们得抛开我们一些自以为是的想法。 我想过这个问题,就是为什么我们背乘法口诀的时候,我们总是背: 22 = 4, 99=81 这样背下去,似乎这是口诀。然而这是缓存,不是计算,既然不是计算那么就不是逻辑学。 我们理所当然的想9*9…

202108120808 - 类加载器及双亲委派机制

Bootstrap ClassLoader 这是加载器中的大 Boss,任何类的加载行为,都要经它过问。它的作用是加载核心类库,也就是 rt.jar、resources.jar、charsets.jar 等。当然这些 jar 包的路径是可以指定的,-Xbootclasspath 参数可以完成指定操作。 这个加载器是 C++ 编写的,随着 JVM …