歐拉篩法求素數


歐拉篩法求素數
     首先,我們知道當一個數為素數的時候,它的倍數肯定不是素數。所以我們可以從2開始通過乘積篩掉所有的合數。
     將所有合數標記,保證不被重復篩除,時間復雜度為O(n)。代碼比較簡單↓_↓

/*求小於等於n的素數的個數*/
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
    int n, cnt = 0;
    int prime[100001];//存素數 
    bool vis[100001];//保證不做素數的倍數 
    scanf("%d", &n);
    memset(vis, false, sizeof(vis));//初始化 
    memset(prime, 0, sizeof(prime));
    for(int i = 2; i <= n; i++)
    {
        if(!vis[i])//不是目前找到的素數的倍數 
        prime[cnt++] = i;//找到素數~ 
        for(int j = 0; j<cnt && i*prime[j]<=n; j++)
        {
            vis[i*prime[j]] = true;//找到的素數的倍數不訪問 
            if(i % prime[j] == 0) break;//關鍵!!!! 
        }
    }
    printf("%d\n", cnt);
    return 0;
}

if(i % prime[j] == 0) break;←_←這一步比較難理解
解釋:
      首先,任何合數都能表示成多個素數的積。所以,任何的合數肯定有一個最小質因子。我們通過這個最小質因子就可以判斷什么時候不用繼續篩下去了。

      當i是prime[j]的整數倍時(i % prime[j] == 0),i*prime[j+1]肯定被篩過,跳出循環。

      因為i可以看做prime[j]*某個數, i*prime[j+1]就可以看做 prime[j]*某個數*prime[j+1] 。而 prime[j] 必定小於 prime[j+1],
所以 i*prime[j+1] 必定已經被 prime[j]*某個數 篩掉,就不用再做了√

      同時我們可以發現在滿足程序里的兩個條件的時候,prime[j]必定是prime[j]*i的最小質因子。這個性質在某些題里可以用到。

      這樣就可以在線性時間內找到素數啦~\(≧▽≦)/~

     

     p.s.這里初學咸魚,如有錯誤歡迎各位大佬們指出~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM