素数筛的2种方法

时间:2019-09-26
本文章向大家介绍素数筛的2种方法,主要包括素数筛的2种方法使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、埃拉托斯特尼(Eratosthenes)筛法

时间复杂度O(n logn)

#include<stdio.h>
#define maxn 100000
bool valid[maxn];

void getprime(int N,int &tot,int ans[]){
    tot=0;
    int i,j;
    for(i=2;i<=N;++i) valid[i]=true;
    for(i=2;i<=N;++i) 
    if(valid[i]){
        if(N/i<i) break;
        for(j=i*i;j<=N;j+=i) valid[j]=false;
        
    }
    for(i=2;i<=N;++i) if(valid[i]) ans[tot++]=i;
    
}

int main(){
    int n,N=1000;  //n为素数数量 ,N为1000以内的素数
    int prime[maxn];  //存储素数值 
    getprime(N,n,prime);
    
        for(int i=0;i<n;i++)
        printf("%d,",prime[i]);
}

二、欧拉(Euler)筛法----线性筛 O(n)

#include<stdio.h>
#include<string.h>
#define  ms(x,v) memset(x,v,sizeof(x)) 

const int MAX=10000;
int prime[MAX+10];        //记录素数值 
int notprime[MAX+10];        //记录每个下标是否是合数,0不是合数1是合数 


int Euler_Prime(int N){
    ms(prime,0);
    ms(notprime,0);
    int n=0;
    int i;
    for(i=2;i<=MAX;i++)
    {
        //如果是素数则记录 
        if(!notprime[i])
        prime[n++]=i;
        
        for(int j=0;j<n;j++)
        {
            if(i*prime[j]>N)  //超过约定的最大数就不考虑了,会由后面的数来筛选,这样就能成线性筛选,使时间复杂度为O(n)     
            break;                
            
            notprime[i*prime[j]]=1;  //比如 i=6时,已存素数2,3,5;则得到 12,18,30为合数 
            
            if(i%prime[j]==0)        //超过p1的就不考虑了,因为在后面会筛 
            break;        //i=4时,只确认了8是合数,而接下来的3*4=12会由6*2来完成,因为否则将会发生重复查询,该算法本就是利用最小质因子来排除合数,
                         //如果发现i能整除某一质因子prime[j],那就跳过,让后面的数来实现i*prime[j]的合数确定
                                              
        }    
    }
    
    return n;
}

int main(){
    int N=1000;//求1000以内的素数 
    int n=Euler_Prime(N) ;
    for(int i;i<n;i++)
    printf("%d ",prime[i]);
}

原文地址:https://www.cnblogs.com/Theo-sblogs/p/11594564.html