您的位置:首页 > 其它

求指定区间内与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无关

如有不当之处欢迎指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: