数论之质数

目录

一、小学知识---何为质数

二、试除法求质数

三、试除法求质因数

四、线性筛法求质数


 

一、小学知识---何为质数

理解什么是质数以及质数的生成规律会对我们写代码有很大的好处

质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

例如:2、3、5、7、11、...

质数x的约数只有两个:1和x。

初等数学基本定理:任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。

二、试除法求质数

我们根据质数的性质可以轻易的使用暴力的算法求出质数

bool is_prime(int x)
{
    if (x < 2) return false;
    for (int i = 2; i < x; i ++ )
        if (x % i == 0)
            return false;
    return true;
}

但是我们考虑到这样的时间复杂度是O(n)我们是否可以对其进行优化呢?

我们知道,如果一个数是合数的化,那么他的约数除了1和自己本身外都是成双出现的

比如12 —>2 ,6;

所以我们并不需要从2到n-1遍历一遍,我们只需要从i遍历到n/i也就是i<=n^{1/2}就可以了

所以优化后的代码:

bool is_prime(int x)
{
    if (x < 2) return false;
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0)
            return false;
    return true;
}

三、试除法求质因数

质因数就是一个数的约数,并且是质数。

  • 1没有质因子。

  • 5只有1个质因子,5本身。(5是质数)

  • 6的质因子是2和3。(6 = 2 × 3)

  • 2、4、8、16等只有1个质因子:2。(2是质数,4 =2²,8 = 2³,如此类推)

  • 10有2个质因子:2和5。(10 = 2 × 5)

 代码:

void divide(int x)
{
    for (int i = 2; i <= x / i; i ++ )
        if (x % 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;
}

我们注意到,上面两行代码和上面的求质数代码一样,当然时间复杂度也是O(sqrt(n))可是这样求出来的是含有约数的,我们上一个代码也是以此为依据来判断的,但是我们现在要求的是质因子,首先其就是一个质数这不就矛盾了吗?其实并没有,我们看到下面的while (x % i == 0) x /= i如果说i是x的约数的话,我们就给它除干净了,所以从2~i-1中不包含i中的任何因子,也就说明i一定是质数!

四、线性筛法求质数

质数定理:1~n中有n/lnn个质数.

朴素筛法的思想:

从2开始,依次将每个素数的倍数标记为合数并剔除直到没有其倍数为止,接着筛下一个没被标记的数

埃氏筛法思想:

只用质数去筛

埃氏筛法的时间复杂度为O(n logn logn)

我们发现有些数被重复标记了好几次,我们可以在这个上进行优化

线性筛法:

// 线性筛素数(以下把prime[j]这个数简写为pj)
// 如何保证线性:一个合数只能被筛掉一次
// 如何保证一个数字只被筛掉一次:这个数字只被它的最小质因数筛掉,当它的其他质因数想要筛掉它时,将无法进行筛除操作
void get_prime(int n) {
    for (int i = 2; i <= n; ++i) {
        if (!st[i]) prime[cnt++] = i; // 如果这个数字没有被记录,那么这个数字必然为素数,记录一下
        for (int j = 0; prime[j] <= n/i; ++j) {
            st[prime[j] * i] = true;  // 筛掉pj*i这个合数
            if (i % prime[j] == 0)  break; // i%pj==0,说明pj是i的最小素因子,因此i*素数的最小素因子也是pj,在i递增的时候也会被筛掉,因此不需要在这里判断
        }                
    }
}

一般用线性筛法,所以只把线性筛法放这。

你可能感兴趣的:(算法基础笔记,算法,数据结构,c++)