[学习笔记]质数
一.质数的判定
枚举$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
时间复杂度是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 的最小质因子,所以肯定会被 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;
}
}
}
三.质因数分解