素数筛法(埃氏筛法和欧拉筛法)

一:埃拉托斯特尼筛法(Sieve of Eratosthenes)

    1.算法的基本思想:

        如果一个数是质数,那么它的倍数肯定非质,利用事先定义的线性表以打表方式标记非质,则剩下的数就是素数。

    2.筛选过程:

    素数筛法(埃氏筛法和欧拉筛法)_第1张图片

//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include ;
#include 
#include 
#include 
#include 
#include 
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef long long ll ;
const int mod = 1e9+7 ;
const int N = 100009 ;
int vis[N];
int a[N];//素数表

int main()
{
    vis[1] = 0 ;
    for(int i = 2 ; i <= N ; i++)//都标记为素数
        vis[i] = 1 ;
    int m = floor(sqrt(N)+0.5) ;
    for(int i = 2 ; i <= m ; i++)
    {
        if(vis[i])
        {
            for(int j = i * i ; j <= N ; j += i)
            {
                vis[j] = 0 ;//利用素数的倍数是合数筛选
            }
        }
    }
    int l = 0 ;
    for(int i = 1 ; i <= N ; i++)
    {
        if(vis[i])
        {
            a[l++] = i ;
            cout << i << endl ;
        }
    }
    return 0;
}

 总结:Eratosthenes筛选法虽然效率高,但是Eratosthenes筛选法做了许多无用功,一个数会被筛到好几次,最后的时间复杂度是O(nloglogn),对于普通素数算法而言已经非常高效了,但欧拉筛选法的时间复杂度仅仅为O(n).

二:欧拉筛选法

1.算法的基本思想:

prime数组 中的素数是递增的,当 i 能整除 prime[j],那么 i*prime[j+1] 这个合数肯定被 prime[j] 乘以某个数筛掉。
因为i中含有prime[j], prime[j] 比 prime[j+1] 小。接下去的素数同理。所以不用筛下去了。
在满足i%prme[j]==0这个条件之前以及第一次满足改条件时,prime[j]必定是prime[j]*i的最小质因子。

//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include ;
#include 
#include 
#include 
#include 
#include 
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef long long ll ;
const int mod = 1e9+7 ;
const int N = 100009 ;
int vis[N];
int a[N];//素数表

int main()
{
    vis[1] = 0 ;
    for(int i = 2 ; i <= N ; i++)//都标记为素数
        vis[i] = 1 ;
    int l = 0 ;
    for(int i = 2 ; i <= N ; i++)
    {
        if(vis[i])
        {
            a[l++] = i ;
        }
        for(int j = 0 ; j < l && i * a[j] <= N ; j++)
        {
            vis[a[j]*i] = 0 ;
            if(i % a[j] == 0) break ;//每一个合数都将被其最小质因数筛去
        }
    }
    for(int i = 0 ; i < l ; i++)
        cout << a[i] << endl;

    return 0;
}

你可能感兴趣的:(素数筛法(埃氏筛法和欧拉筛法))