素数相关算法

1 求解n以内的素数个数

1.1 暴力法

1.2 埃式筛法

我们考虑这样一个事实:如果 x 是质数,那么大于 x 的 x 的倍数 2x,3x… 一定不是质数,因此我们可以从这里入手。

我们设 isPrime[i] 表示数 i 是不是质数,如果是质数则为 1,否则为 0。从小到大遍历每个数,如果这个数为质数,则将其所有的倍数都标记为合数(除了该质数本身),即 0,这样在运行结束的时候我们即能知道质数的个数。

这种方法的正确性是比较显然的:这种方法显然不会将质数标记成合数;另一方面,当从小到大遍历到数 xx 时,倘若它是合数,则它一定是某个小于 x 的质数 y 的整数倍,故根据此方法的步骤,我们在遍历到 y 时,就一定会在此时将 x 标记为 isPrime[x]=0。因此,这种方法也不会将合数标记为质数。

当然这里还可以继续优化,对于一个质数 x,如果按上文说的我们从 2x 开始标记其实是冗余的,应该直接从 x⋅x 开始标记,因为 2x,3x… 这些数一定在 x 之前就被其他数的倍数标记过了,例如 2 的所有倍数,3 的所有倍数,…,x-1的所有倍数。

两个要注意的点:

  • 当前要判断的数x为质数,才需要赋值它的倍数2x3x4x为合数
  • 关于倍数,当要将x的倍数置为合数时,其实可以直接从x*x倍开始,因为2 ~ x-1倍,早已被2 ~ x-1的倍数计算过了。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/count-primes/solution/ji-shu-zhi-shu-by-leetcode-solution/

例题:Leetcode 204. 计数质数

int countPrimes(int n) {
    bool prime[5000000 + 7];
    memset(prime, true, sizeof(prime));
    prime[0] = false;
    prime[1] = false;
    int ans = 0;
    for (int i=2; i<n; ++i) {
        if (prime[i] == true) {
            ++ ans;
            if ((long long)i*i < n) {
                for (int j=i*i; j<n; j+=i) {
                    prime[j] = false;
                }
            }
        }
    }
    return ans;
}

1.3 线性筛法

2 欧拉公式

欧拉公式,用来解决所有小于n中的正整数中有多少个与n互质。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值