码迷,mamicode.com
首页 > 其他好文 > 详细

素数筛法知识点整理

时间:2018-08-16 17:45:39      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:大于   正整数   max   两种   name   nlog   turn   除了   span   

素数的定义:除了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)呢?其实原因就是

素数筛法知识点整理

标签:大于   正整数   max   两种   name   nlog   turn   除了   span   

原文地址:https://www.cnblogs.com/acgoto/p/9488304.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!