容斥原理——经典例题(组合数学)
一.容斥原理
就是人们为了不重复计算重叠部分,想出的一种不重复计算的方法。
先来认识一下这两个符号:与(如图)
蓝色的圈就是c1c2,红色的圈围起来的就是c1c2
二.例题:组合数学
1.题目
1.1.题目描述
八是个很有趣的数字啊。八=发,八八=爸爸,88=拜拜。当然最有趣的还是8用二进制表示是1000。怎么样,有趣吧。当然题目和这些都没有关系。 某个人很无聊,他想找出[a,b]中能被8整除却不能被其他一些数整除的数。
1.2.输入
第一行一个数n,代表不能被整除的数的个数。 第二行n个数,中间用空格隔开。 第三行两个数a,b,中间一个空格。 a < =b < =1000000000
1.3.输出
一个整数,为[a,b]间能被8整除却不能被那n个数整除的数的个数。
1.4.样例输入
3
7764 6082 462
2166 53442
1.5.样例输出
6378
1.6.提示
对于30%的数据, 1 ≤n ≤5,1 ≤a ≤ b ≤ 100000。
对于100%的数据,1 ≤ n ≤15,1 ≤ a ≤ b ≤ 10^9,N个数全都小于等于10000大于等于1。
2.思路
这道题一看就是用容斥原理做吧,如果我们用ans表示答案,用B表示a到b的范围内可以被8整除的所有数,用E表示a到b范围内的所有数,Ai表示那n个要求不能整除的数,可以想到公式:
它的意义就是:所有范围内的数减去所有能被那n个数整除的数与所有范围内能被8整除的数的并集。
好,那么我们现在的问题就是如何求这些并集。(注意求两个数的并集就是求两个数的最小公倍数)
先举一个例子:假如有两个要求不被整除的数(如图,那两个数分别为1号圈和2号圈):
那么,也就是:ans=8-①-②+②-②-③
再来一个稍复杂的:
继续像例子1这样推:
说人话,就是:ans=8-(①+⑤+④+②)+(②+④)-(④)+(④+⑤) -(③+②+④)+(④) -(④+⑤+⑥)
可化简为:ans=8-①-②-④-③-⑤-⑥,就是我们想要求的答案了。大家可以发现,我打了下划线的部分是各个完整的部分,分别是8与其他数分别第一次并集
然后8与这个数并集之后,又依次与其他的数继续并集,并且不重不漏,还有,在一个完整的部分里第奇数次并集相减,第偶数次相加,如:ans=8-(①+⑤+④+②)+(②+④)-(④)+(④+⑤) -(③+②+④)+(④) -(④+⑤+⑥)
从8的集合开始,第0次加上8的集合内的所有数,到开始第1次-(①+⑤+④+②)相减,第2次(②+④)相加,然后发现不能再并下去了,又回到,开始新的第1次-(④),第2次(④+⑤),发现也不能再走下去了,就到了,继续走下去就走完了。所以,这就是一个递归进行的过程,一个深搜就完事了。
void dfs (int k, int Index, LL v){//k代表第几次并集,Index代表到了第几个集合,v代表这个集合,如v=8,就代表8的倍数这个集合if (v > b)//超出范围就没有意义return ;if (k % 2 == 0)//第偶数次加,第基数次减ans += b / v - a / v;elseans -= b / v - a / v;for (int i = Index + 1; i <= n; i ++){LL t = lcm (v, m[i]);//求着两个集合的并集dfs (k + 1, i, t);//递归求解}
}
3.代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define LL long long
int n, m[130], a, b;
LL ans;
LL gcd (LL a, LL b){//最大公因数if (! b)return a;return gcd (b, a % b);
}
LL lcm (LL a, LL b){//最小公倍数return a * b / gcd (a, b);
}
void dfs (int k, int Index, LL v){//k代表第几次并集,Index代表到了第几个集合,v代表这个集合,如v=8,就代表8的倍数这个集合if (v > b)//超出范围就没有意义return ;if (k % 2 == 0)//第偶数次加,第基数次减ans += b / v - a / v;elseans -= b / v - a / v;for (int i = Index + 1; i <= n; i ++){LL t = lcm (v, m[i]);//求着两个集合的并集dfs (k + 1, i, t);//递归求解}
}
int main (){scanf ("%d", &n);for (int i = 1; i <= n; i ++)scanf ("%d", &m[i]);scanf ("%d %d", &a, &b);dfs (0, 0, 8);//从第0次开始printf ("%lld\n", ans);return 0;
}
4.感想
这道题的深搜是最考验人的,有时候只要带一些例子进去算一下就豁然开朗了。
容斥原理——经典例题(组合数学)相关推荐
- [二分查找] 二:二分查找的经典例题
1.何时应该会使用二分查找 当题目中出现有序数组时 当时间复杂度要求为log(n)时 搜索范围可以一次缩小一半时 2. 经典例题1 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果 ...
- 双指针算法(三):力扣【167.两数之和 | 经典例题
本文将讲述双指针算法的一个经典例题,167.两数之和 [题目描述] 给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target . 函数应该以长 ...
- c语言 异或_C语言经典例题来袭!5大方法告诉你答案
各位,今天我们来看一个C语言的经典例题,因为最近有不少人后台问的问题都跟这个或多或少有点关系,所以今天咱们拿出来对这类问题进行一个总结,话不多说,就问下面的代码会输出什么? #include 意图很明 ...
- 华为杯数学建模优秀论文_数学建模经典例题(2011年国赛A题与优秀论文)
数学建模经典例题 (更多往期经典例题可点击文章最后相关推荐哦) 试题中的附件1.2和3请点击"阅读原文"查看 相关推荐数学建模经典例题(2000年国赛A题与优秀论文)数学建模经典例 ...
- PHP盈亏问题,小升初数学必考经典应用题—盈亏问题!(附经典例题分析)
这种题目中往往有两种分配方案,每种分配方案的结果会出现多(盈)或少(亏)的情况,通常把这类问题,叫做盈亏问题(也叫做盈不足问题). 解答这类问题时,应该先将两种分配方案进行比较,求出由于每份数的变化所 ...
- c语言变量相等问题穷举法,C语言穷举法经典例题.ppt
<C语言穷举法经典例题.ppt>由会员分享,可在线阅读,更多相关<C语言穷举法经典例题.ppt(18页珍藏版)>请在人人文库网上搜索. 1.枚举法(穷举法),"笨人之 ...
- 复杂电路简化经典例题_【中考物理】电路简化的10大原则和7大步骤
电路问题是初中物理比较难的知识,也是中考很重要的一部分.很多同学遇到电路类的题目,摆在面前的第一个问题就是不会简化电路图. 今天给大家分享电路简化的10大原则和7大步骤,希望能够帮你解决这个难题! 电 ...
- 华为杯数学建模优秀论文_数学建模经典例题(2016年国赛B题与优秀论文)
数学建模经典例题 (更多往期经典例题可点击文章最后相关推荐哦) 相关推荐 数学建模经典例题(2000年国赛B题与解题思路) 数学建模经典例题(2001年国赛A题与优秀论文) 数学建模经典例题(2001 ...
- 华为杯数学建模优秀论文_数学建模经典例题(2013年国赛A题与优秀论文)
数学建模经典例题 (更多往期经典例题可点击文章最后相关推荐哦) 相关推荐 数学建模经典例题(2000年国赛B题与解题思路) 数学建模经典例题(2001年国赛A题与优秀论文) 数学建模经典例题(2001 ...
- c语言 正整数 几位 逆序,c语言经典例题:正整数求位数and求顺、逆序位数
经典例题:正整数求位数and求顺.逆序位数 题目要求: 给出一个int整形正整数,要求: 1.求出它是几位数字 2.按照逆序分别输出每位数字,例如123输出为321 3.按正序输出每位数字 分析: 一 ...
最新文章
- Plant J:细菌挥发性物质和光合信号激活低铁响应途径
- 如何着手学习一个新的PHP框架
- linux /proc/net/tcp 文件分析
- spring+cxf 开发webService(主要是记录遇到spring bean注入不进来的解决方法)
- Celery定时任务异步任务
- Sonar 质量扫描的输出日志--对应源码的跟踪(一){源码解析sonar-scanner-maven3.2}
- 针对SQL INJECTION的SQL SERVER安全设置初级篇
- ThinkPHP3.2.3分页中文参数乱码问题及解决
- CSS中的contenteditable属性
- MapReduce编程模型简介和总结
- Win10外接显示频黑屏解决
- 飞行管理计算机系统主要由什么组成,飞机结构介绍-飞行管理计算机系统.pdf
- Ceph Calamari安装问题汇总
- MATLAB 过时了吗?
- ECNU || 宇恒棋
- gallery3d的源码分析——入口
- HTML5学习_day10(4)--兼容性个例
- 深度学习初学者推荐怎么在本地完成CS231n课程作业-配置环境
- 1.1 input()函数--输入
- 走进MySQL---分享dept、emp、bonus、salgrade员工信息管理表