素数筛法知识点整理

Posted acgoto

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了素数筛法知识点整理相关的知识,希望对你有一定的参考价值。

素数的定义:除了1和它本身之外,不能被其他整数整除。

一、判定一个正整数n是否为素数的方法:

①定义法:枚举2~n-1这n-2个正整数,如果它们均不能整除n,则可断定n为素数。代码如下:时间复杂度为O(n),如果n为10^9,就不能用此方法。

1 bool is_prime(int n){
2     if(n==1)return false;
3     for(int i=2;i<n;++i)
4         if(n%i==0)return false;
5     return true;
6 }

②从2开始枚举到不大于sqrt(n)的所有正整数,如果它们均不能整除n,则可断定n为素数。为什么只需枚举到sqrt(n)就可以了呢?理由:假设n存在大于或等于sqrt(n)的因子y,则z=n/y必同时为n的因子,且其值小于或等于sqrt(n)(如果z>sqrt(n),那么z*y>n与n=z*y相矛盾)。所以,若n存在相异于1和它本身的因子y>sqrt(n),则必存在小于或等于sqrt(n)的因子,因此,我们只需测试因子到sqrt(n)即可。时间复杂度为O(sqrt(n))。

1 bool is_prime(int n){
2     if(n==1)return false;
3     for(int i=2;i*i<=n;++i)
4         if(n%i==0)return false;
5     return true;
6 }

二、给定一个正整数n(n<=10^6),问n以内有多少个素数?如果采用方法2,时间复杂度最坏能达到1e9!!!超时是毫无疑问的,那么是否有比较快速的判断方法呢?于是两种经典筛法就呼啦呼啦地闪亮登场了。

埃氏筛法要得到自然数n以内的全部素数,必须把不大于sqrt(n)的所有素数的倍数剔除,剩下的都是素数。时间复杂度只有O(nloglogn),非常接近O(n)。方法:最小的素数是2,先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去......最后剩下的一定是素数,根据定义,下面给出埃氏筛的两种写法:一种是直接判定素数,另一种是边判定素数边保存素数,代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000;
 4 bool isp[maxn];int cnt=0,prime[maxn];
 5 void sieve1(){//1、直接判定素数
 6     memset(isp,true,sizeof(isp));
 7     isp[0]=isp[1]=false;
 8     for(int i=2;i*i<maxn;++i){
 9         if(isp[i]){
10             for(int j=i*i;j<maxn;j+=i)
11                 isp[j]=false;
12         }
13     }
14 }
15 void sieve2(){//2、边判定素数边保存素数
16     memset(isp,true,sizeof(isp));
17     memset(prime,0,sizeof(prime));
18     isp[0]=isp[1]=false;
19     for(int i=2;i<maxn;++i){
20         if(isp[i]){//如果isp[i]==true,则i一定是素数
21             prime[cnt++]=i;//保存素数
22             for(int j=i*i;j<maxn;j+=i)
23                 isp[j]=false;
24         }
25     }
26 }
27 int main(){
28     sieve1();//测试代码
29     for(int i=1;i<maxn;++i)
30         if(isp[i])cout<<i<<endl;
31     /*sieve2();
32     for(int i=0;i<cnt;++i)
33         cout<<prime[i]<<endl;*/
34     return 0;
35 }

疑难点一:根据埃氏筛的定义,枚举不大于sqrt(n)的所有素数,将其倍数剔除掉,最终留下的都是素数,为什么只需枚举到sqrt(n)呢?其实原因就是


以上是关于素数筛法知识点整理的主要内容,如果未能解决你的问题,请参考以下文章

常用积性函数的线性筛法整理

代码模板——素数筛法

素数的筛法

素数筛法(Eratosthenes筛法)

练习筛法遍历素数(Java)

筛法求素数