数学--质数

质数

1只包含 1 1 1和本身两个约数


1. 判断质数

试除法,只需枚举 2 ∼ n 2 \sim \sqrt{n} 2n 即可

  1. 代码:
bool is_prime(int n)
{
    if (n < 2) return false;
    for (int i = 2; i <= n / i; i ++ )
        if (x % i == 0)
            return false;
    return true;
}
  1. 细节
  • 不推荐写 n \sqrt{n} n ,因为要调用函数,太慢。
  • 不推荐写 i × i < = n i \times i <= n i×i<=n,当 n n n太大时, i × i i \times i i×i有可能溢出。

2. 分解质因数

n n n最多只含一个 > n >\sqrt{n} >n 的质因子,仍使用试除法,遇到约数就约掉。如果约掉了所有 < n <\sqrt{n} <n 的质因子之后,剩余的数仍大于 1 1 1,则剩下的数必是质因子,单独处理即可。

代码:

void divide(int n)
{
    for (int i = 2; i <= n / i; i ++ )
        if (n % i == 0)
        {
            // 约掉所有因子,易证从小到大约掉的因子必是质因子
            int s = 0;
            while (x % i == 0) x /= i, s ++ ;
            cout << i << ' ' << s << endl; // 输出质因子及其个数
        }
    if (x > 1) cout << x << ' ' << 1 << endl; // 单独处理最后一个因子
    cout << endl;
}

3. 筛质数

给定一个范围 1 ∼ n 1 \sim n 1n,筛掉范围内所有的质数。

(1) 朴素筛法 → O ( n × log ⁡ n ) \to O(n \times \log n) O(n×logn)
  1. 思路:从 2 ∼ n 2 \sim n 2n枚举,依次筛掉 2 2 2的倍数、 3 3 3的倍数、 4 4 4的倍数,以此类推。

  2. 例题: 洛谷P5736 【深基7.例2】质数筛

(2) 埃氏筛法 → O ( n × log ⁡ ( log ⁡ n ) ) \to O(n \times \log(\log n)) O(n×log(logn))
  1. 优化:

只筛掉质数的倍数,例如在(1)中枚举到 4 4 4,由于 4 4 4已经在 2 2 2的时候就被筛掉了,就跳过 4 4 4不再筛 4 4 4的倍数了。显然,如果枚举到某个数 i i i,且 i i i之前没有被筛掉,那么 i i i必是质数。

  1. 缺点:仍旧还是有些数被重复筛了,例如 6 6 6会被 2 2 2 3 3 3同时筛掉,效率仍待提高。
(3) 线性筛法 → O ( n ) \to O(n) O(n)
  1. 优化:每个数只会被自己最小的质因子筛掉,例如上面 6 6 6只会被 2 2 2筛掉。

  2. 思路:

  • i   m o d   p j = 0 → p j i \bmod p_j = 0 \to p_j imodpj=0pj一定是 i i i的最小质因子, p j p_j pj也一定是 p j × i p_j \times i pj×i的最小质因子。
  • i   m o d   p j ≠ 0 → p j i \bmod p_j \neq 0 \to p_j imodpj=0pj一定小于 i i i的所有质因子, p j p_j pj也一定是 p j × i p_j \times i pj×i的最小质因子。
  • 按照此逻辑来决定一个数一个数地筛。
  1. 代码:
int primes[N], cnt;      // primes[]存储所有素数
bool st[N];           // st[x]存储x是否被筛掉

void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
  1. 例题 洛谷P3383 【模板】线性筛素数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值