求指定区间内与n互素的数的个数 容斥原理
2017-05-12 00:07
816 查看
题意:给定整数n和r,求区间[1, r]中与n互素的数的个数。
如果使用暴力的方法, 枚举1...n, 判定gcd(i,n)是否为1的复杂度是log(max(i,n)),总的复杂度就是r∗log(max(i,n))。当r特别大的时候,时间效率会非常低下,那么我们可以考虑容斥定理。
容斥定理的思想:去求解原问题的逆问题−求区间[1,r]中不与n互素的个数。
思路:首先求得n的所有素因子Pi(i=1...k), 通过二进制枚举所有素因子的组合, 如果选取了奇数个素
因子,应该加上对应的个数,而如果是偶数, 则减去即可。
例如6既能2整除,也能被2∗3整除,所以应该剔除重复计数的部分(使用容斥定理)。
假设当前得到的素数组合是k, 那么⌊rk⌋就是[1,r]中能被k整除的数的个数。
详细见容斥定理
详细代码如下
int solve(int r, int n) { vector<int>p; p.clear(); for(int i = 2; i*i <= n; ++i) { if(n % i == 0) { p.push_back(i); while(n % i == 0) n /= i; } } if(n > 1) p.push_back(n); //可能n也是素数 int sum = 0; for(int msk = 1; msk < (1<<p.size()); ++msk) { int mult = 1, bits = 0; for(int i = 0; i < p.size(); ++i) { if(msk & (1<<i)) { //选择了第i个素数因子 bits++; mult *= p[i]; } } int cur = r / mult; if(bits & 1) sum += cur; else sum -= cur; } return r - sum; }
该算法复杂度是n√, 和r无关
如有不当之处欢迎指出!
相关文章推荐
- 组合数学-容斥原理-求指定区间内与n互素的数的个数
- 经典问题:求区间内与n互素的数的个数(容斥原理)(4135)
- 区间互素(筛法欧拉函数模板+容斥原理)(1695)
- Excel用FREQUENCY统计数值的在指定区间内出现频率
- 二叉排序树查找指定区间的值
- Python产生指定区间的随机数组
- 003-20利用伴随数组解决在指定区间第k小(大)的数——重复查看,区间任意
- 生成闭区间随机指定维度数组方法
- TCL脚本语言-生成指定区间的随机数-rand-RandomRange
- 获取指定时间区间内的月份
- C语言 - 斐波那契数列(Fibonacci) 指定区间输出
- Spark2 feature Bucketizer之将连续数据离散化到指定的范围区间
- 北航11年机试--求指定区间内的孪生数
- 巧用润乾内置函数获取指定日期所在时间区间
- 巧用V5内置函数获取指定日期所在时间区间
- 第1章第2节练习题4 删除指定区间结点
- c#产生指定区间的随机数
- 容斥原理应用(求1~r中有多少个数与n互素)
- 关于在指定区间求第k小的数,求高效率算法
- [LeetCode-92] Reverse Linked List II(反转指定区间链表)