[学习笔记]质数

一.质数的判定

枚举$2~\sqrt{n}$,判断能否被整除.

1和0既不是质数也不是合数.

二.质数的筛选

1.朴素筛法

朴素筛法就是枚举1~n,分别判断他们是不是素数.

复杂度O($ \sum_{i=2}^n \sqrt{i} $).

几乎用不到.

2.Eratosthenes筛法

找到一个质数,把这个质数的倍数都筛去.

void prework(){
    for(int i=2;i<=n;++i){
        if(!vis[i]){
            p[++p[0]]=i;
            for(int j=i*i;j<=n;j+=i)
            vis[j]=1;
        }
    }
}

这里从i*i开始就行了,因为$ j \times i(j<i) $ 会被之前j的$ i $倍筛掉.

时间复杂度是O(nlogloogn),效率非常接近线性.

比较容易记忆,不易写错,用埃筛的思想还可以做这道题https://www.cnblogs.com/huihao/p/11742014.html

3.线性筛法(欧拉筛)

Eratosthenes筛法会重复标记合数,比如12会被2,3标记.也就是筛去12的方式不唯一,导致每个合数筛去的次数可能不止一遍,导致算法不是线性,在数据接近极限的时候Eratosthenes筛法可能会超时.

线筛对于每一个合数只会被他的最小值质因子筛去,每个数的最小质因子唯一可确保每个质数只会被筛去一次.

还是埃筛的思路,把质数的倍数标记为合数.但在找到质数时,并不着急筛去他的倍数.

埃筛的内层是倍数,线筛的外层是倍数. 素数$ p[j] $的$ i $倍. p[j]<=i;

也就是说 p[j]*i全是合数,要筛去,但又得保证p[j]是他的最小值质因子, 由于p[j]是递增的 当 i%p[j]==0 是 p[j] 就一定是i的最小质因子此时 p[j + 1]就 一定大于i的最小质因子,也就是说 p[j+1] * i 的最小质因子不是p[j + 1],所以当i%p[j]==0时就可以跳出循环.

那这样能保证每个合数都被筛到吗?

考虑合数 x. 设他的最小质因子为 i . 令 j=x/i; 则 x=i*j; 由i的性质可知 i<j, 且i小于j的最小质因子.

当外层循环到 j 时,由于 i 小于 j 的最小质因子,所以肯定会被 i*j 筛掉.

void get_prime(){
    for(int i=2;i<=n;++i){
        if(!vis[i])
            p[++p[0]]=i;
        for(int j=1;j<=p[0]&&1LL*i*p[j]<=n;++j){
            vis[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }
}

 留坑..

三.质因数分解

我懒....

 

posted @ 2019-10-26 11:09  沐灵_hh  阅读(280)  评论(0编辑  收藏  举报