第三十六章 数论——容斥原理

news/2024/11/16 14:48:22/

第三十六章 数论——容斥原理

一、容斥原理

1、定理内容

我们在高中阶段都学过韦恩图,韦恩图其实就是用来描述集合与集合之间的关系的。

我们看下面的图:
请添加图片描述
这道题的话,我们首先将三个圆圈加在一起,但是叶子形状的部分会被我们重复加了两遍,所以我们要减去。但是三个叶子形状的中间也会有交叉的部分。所以这个部分又被我们减少了三次。所以我们还要再加上一次中间部分。

因此,就出现了我们图中的红色式子。

因此,我们总结出了一个规律。如果我们求的是奇数个集合的合并,那么我们就要加上。如果是偶数个集合的合并,我们就要减去。

那么我们从这个特殊的例子推广到一般情况,就会得到如下公式:
请添加图片描述
而这个式子就是我们的容斥原理

那么容斥原理的时间复杂度是多少呢?

我们可以看作我们的前面有nnn个集合SSS,那么我们从中选出1个集合就是Cn1C_n^1Cn1
选出任意两个集合的交集,就是Cn2C_n^2Cn2

那么依次类推:

我们选出所有集合所需的情况就是:

Cn1+Cn2+Cn3+...+CnnC_n^1+C_n^2+C_n^3+...+C_n^nCn1+Cn2+Cn3+...+Cnn

而根据我们高中的知识:
Cn0+Cn1+Cn2+Cn3+...+Cnn=2nC_n^0+C_n^1+C_n^2+C_n^3+...+C_n^n=2^nCn0+Cn1+Cn2+Cn3+...+Cnn=2n

那么我们选出所有情况来运用容斥原理计算的次数就是:

Cn1+Cn2+Cn3+...+Cnn=2n−1C_n^1+C_n^2+C_n^3+...+C_n^n=2^n-1Cn1+Cn2+Cn3+...+Cnn=2n1

时间复杂度就是O(2n)O(2^n)O(2n)

二、代码模板

1、问题

在这里插入图片描述

这道题可以转化成下面的图片:

请添加图片描述
紫色圈代表能够被p1整除的,绿色圈代表能被p2整除的,依此类推。题目中就是让我求上图中的元素个数。

如果我们只是单纯的把被某个数整除的数字个数加起来的话,中间一定会有重复的。因此,我们需要根据容斥原理来求。

利用容斥原理的话,我们有以下几个问题:

(1)如何求出能够被整除的个数?

其实很简单,能被p1p_1p1整除的个数是[Np1][\frac{N}{p_1}][p1N]

中间的交集的话,我们以能够被p1p_1p1或者p2p_2p2为例。我们只需要求[Np1∗p2][\frac{N}{p_1*p_2}][p1p2N]

依次类推。

(2)如何枚举出2n−12^n-12n1种情况?

那么这个枚举的话,可以采用二进制的思想,我们的情况一共是2n−12^n-12n1种,我们将其转化为二进制的话,(以n=3)为例:

23−1=1112^3-1=111231=111

每一位代表一个集合,此时三位都是1,说明我们要求三个集合的交集

那么如果是101101101,就代表我们要求第一个集合和第三个集合的交集。

而我们的所有情况无非就是从001−111001-111001111,换算为十进制的话,我们就是要枚举从1112n−12^n-12n1。这中间的每个数字的二进制位都代表着一种情况。

当上述两个问题解决之后,我们就可以套用容斥原理的公式了。

2、代码实现:

#include<iostream>
using namespace std;
typedef long long LL;
const int N=20;
int p[N];
int main()
{int n,m,res=0;cin>>n>>m;//读取除数for(int i=0;i<m;i++)scanf("%d",p+i);//枚举情况for(int i=1;i<1<<m;i++){//t用来记录结果,s用来记录集合的个数int t=1,s=0;//枚举情况i的二进制位for(int j=0;j<m;j++){if(i>>j&1)//如果这一位是1,那么就让该位对应的集合参与运算{if((LL)t*p[j]>n)//如果几个数的积,已经大于了n,那么这种情况不存在。{t=0;//如果不存在了,就直接扔掉就好了。break;}t*=p[j];//乘上该集合所对的除数s++;//记录参与的集合个数}}if(t){//使用容斥原理:if(s%2)res+=n/t;//如果集合是奇数就加上else res-=n/t;//如果集合是偶数就减去}}cout<<res<<endl;
}

http://www.ppmy.cn/news/7726.html

相关文章

Android插件化换肤原理—— 布局加载过程、View创建流程、Resources 浅析

前言 继上次 WebView 干货分享后&#xff0c;本次将分享下自己在探索学习 App 换肤功能过程中的相关知识&#xff0c;着重分享换肤的原理以及实现思路。 由于篇幅原因分为两篇博客&#xff0c;本文主要分析了 Android 布局加载流程&#xff0c;下一篇将具体讲解插件化换肤实现…

pure pursuit纯跟踪

Pure Pursuit是一种几何追踪方法,速度越小,performance越好; :汽车前轮转角 L:前后轮轴距(车长) R:转弯半径 将车辆模型简化为自行车模型(这里默认左轮和右轮的旋转是一致的)!!! bicycle model: pure pursuit建立于自行车模型和阿克曼小车模型的基础上,goal point为距离后…

linux的权限

前言 学习权限我们先理解一下xshell 我们使用Xshell的存在的意义 帮助进行命令行传递和返回结构保护操作系统 linux的权限 (1)权限的概念 限制人的&#xff0c;访问的对象可能没有这种“属性” 权限&#xff1a;一件事情是否运行被谁“做” 权限 人 事物属性 (2)linux的上…

【STM32F4系列】【HAL库】【自制库】模拟IIC主机

介绍 本项目是利用GPIO模拟I2C的主机 网上常见的是模拟I2C主机 本项目是作为一个两个单片机之间低速通信的用法 协议介绍请看,传送门 模拟从机请看这里 主机 功能描述 I2C按字节(Byte)读写I2C读写寄存器I2C连续读写 编程思路解析 主机是时钟信号的发起方,起始和中止信号…

什么样的GPU云计算平台的是好的平台

GPU云计算平台产品解析。通过不同平台不同阶段进行产品分析。究竟我们是需要更便宜还是需要更好用。 第一阶段分为以下几个模块 GPU 选型、 环境选型、 启动实例、 关闭实例。 第二阶段分为以下几个模块 实例关闭策略、无卡模式启动、实例状态监控、提供对外接口、云文件管…

终极.NET混淆器丨.NET Reactor产品介绍

无与伦比的 .NET 代码保护系统&#xff0c;可完全阻止任何人反编译您的代码。 产品优势 01、混淆技术 .NET Reactor通过向 .NET 程序集添加不同的保护层来防止逆向工程。除了标准的混淆技术之外&#xff0c;它还包括NecroBit、虚拟化、x86代码生成或防篡改等特殊功能。NET Re…

Vue--》超详细教程——vite脚手架的搭建与使用

目录 vite 创建 vite 项目 目录文件的构成 vite项目的运行流程 开发者工具安装 vite vue官方提供了两种快速创建工程化的SPA项目的方式&#xff0c;一种是基于 vue-cli 创建的SPA项目&#xff0c;另一种就是基于 vite 创建的SPA项目。两者的区别如下&#xff1a; 说明v…

Linux——磁盘在网络中共享

实现计算服务器挂载存储服务器磁盘 方法一&#xff1a;通过启动nfs服务实现挂载 流程可参考&#xff1a;在linux挂载另一台服务器的磁盘 启动nfs服务参考&#xff1a;Linux 环境下 NFS 服务安装及配置使用 避免存储server的非root用户访问共享文件夹 在存储server上多设置一…