[题解]《算法零基础100讲》(第29讲) 容斥原理 |
您所在的位置:网站首页 › 容斥原理例题精讲 › [题解]《算法零基础100讲》(第29讲) 容斥原理 |
文章目录
一. 容斥原理1.1 集合AUB1.2 集合AUBUC
二. 知识回顾三. 课后习题3.1 丑数 III3.2 播放列表的数量
一. 容斥原理
容斥原理在我们的高中数学中由了解过,就是两个集合A,B的并集的元素个数。同样,在大学里的概率论中也会讲解。 1.1 集合AUB在概率论中,我们有这样的一个公式: A U B = A + B - (A∩B)如图:
如图: 以此类推。 二. 知识回顾推荐专栏: 算法零基础100讲》(第14讲)最小公倍数 由于今日的题解需要用到最小公倍数,所以我们需要回顾一下,最小公倍数的计算方法。通过定理我们可以很明确的知道,a和b的最小公倍数就等于(a * b) / gcd(a,b)。 三. 课后习题 3.1 丑数 III题目链接: 1201. 丑数 III 思路分析: 题目要求我们找出第n个丑数,而题目给定丑数的定义为,能够被a,b,c,整除的数。所以我们最容易想到的就是暴力枚举,从1开始枚举,当遇到a,b,c的约数时,便记录下来,直到找到第n位。 代码如下: int nthUglyNumber(int n, int a, int b, int c){ int i = 1; int Ugly = 0; int cnt = 0; while (i){ if (i % a == 0){ cnt++; } else if (i % b == 0){ cnt++; } else if (i % c == 0){ cnt++; } if (cnt == n){ Ugly = i; break; } i++; } return Ugly; }但题目给定的数据范围为[1,2000000000],很明显暴力的解法会超时,而这种时候我们就得想到一种时间复杂度更快的方法,所以我们很容易会想到O(logn)的二分法,但是这种解法与该题由上面联系呢? 接下来我们进行进一步的分析。 首先我们需要知道的是一个数 a 的约数中,小于n的约数个数为 [n / a];然后我们还需知道,两个数的a,b的公约数中,小于n的公约数个数为 [n / lcm (a, b)] ,其中lcm是最小公倍数。现在我们假设ab , ac , bc分别为a和b,a和c,b和c的最小公倍数,abc为a,b,c的最小公倍数,假设他们不大于n丑数有m个,则m = n / a + n / b + n / c - n / ab - n / ac - n / bc + n / abc。 有了上面的m,我们在结果区间[1,2000000000]上取中间值mid,计算不大于mid的丑数有m个,我们便可以对m与题目所给的n(这里的n是题目给的n)进行比较,如果m < n则说明小于mid的丑数还不够n个,那么我们就需将mid增大,便将区间转化为[mid + 1,2000000000],在从中找出新的mid,继续进行比较,直到区间重合,此时的区间值就是我们所求的第n个丑数的值。 代码如下: #define ll long long //计算表最大公约数 int gcd(int a, int b){ return !b ? a : gcd(b, a % b); } //计算最小公倍数 ll lcm(int a, int b){ return (ll)a / gcd(a, b) * b; } int nthUglyNumber(int n, int a, int b, int c){ ll ab = lcm(a, b);//a 和 b的最小共倍数 ll ac = lcm(a, c);//a 和 c 的最小共倍数 ll bc = lcm(b, c);//b 和 c 的最小公倍数 ll abc = lcm(lcm(a, b), c);//a, b, c的最小公倍数 int left = 1, right = 2000000000; while(left |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |