1. 程式人生 > >埃氏篩法

埃氏篩法

== 素數 基本思想 pro 找到 依次 () mes 讀取

埃氏篩法的基本思想:

這個東西的基本思路就是首先把1~n中小於2的數先標記,因為這些數字都不是質數。之後我們依次標記這個裏面所有質數的倍數,直到這個質數的平方要大於n的時候,我們就停止這個程序。這樣我們剩下沒有標記的數就是要求的質數了。沒有如果你還不理解的話,我們就來舉一個例子:加入我們要求出1~25裏面的所有質數,我們可以這麽做。首先這個裏面的第一個質數是2,所以我們要標記所有大於2的倍數,之後下一個質數就是3,我們就標記所有大於3的倍數,這樣做直到6,現在6的平方大於25,就結束程序。、

這個裏面還有一個小技巧,就是加入我們知道了當前的質數,我們要怎麽知道下一個質數。我們可以發現,加入我們標記了當前質數的所有比它大的倍數之後我們從當前質數開始往下枚舉,遇到第一個沒有被標記的數就是下一個質數了。

註意:我們在循環變量裏盡量使用 register 類型的變量這樣可以加快整個程序,防止被卡常,因為 register 類型的變量是放在CPU寄存器裏的,這樣變量 讀取/寫入 的速度要比在內存裏快很多 至少要快兩倍

模板題:

洛谷 [p3912]
是不是想寫寫看這個算法?這裏剛好有一個模板題來測這個算法。

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e8+5;

int n;
bool check[N]; //如果check [i] == false 表示 i 是一個素數  

int main()
{
    scanf("%d",& n);
    
    register int p=2;check[1]=true;
    while(true)
    {
        if(p*p>=n)
            break;
        
        //先標記合數 
        for(register int i=p+p;i<=n;i+=p)
            check[i]=true;
            
        //找到下一個質數 
        for(register int i=p+1;i<=n;i++)
        {
            if(!check[i])
            {
                p=i;
                break;
            }
        }
    }
    
    register int ans=0;
    for(register int i=1;i<=n;i++)
    {
        if(!check[i])
            ans++;
    }
    
    printf("%d\n",ans);
    
    return 0;
}

埃氏篩法