質數篩演算法詳解

2022-09-11 13:27:33 字數 1748 閱讀 7474

今天給大家講解質數篩這個演算法。

在資訊競賽中,我們總是會遇到很多判斷質數的題目,那麼在這裡就由我來給大家講解一下質數篩演算法(這裡所有講的演算法都是基於篩出從 \(1\) 到 \(n\) 之間的素數的演算法)。

最普通的篩法,也就是將前 \(n\) 個正整數乙個乙個來判斷是否為素數,並且在判斷素數的時候要從 \(2\) 列舉到 這個數\(-1\) 來判斷。

關鍵**

for(int i=1;i<=n;++i)//列舉1到n

\) 就可以判斷出來了。

關鍵**

for(int i=1;i<=n;++i)//列舉1到n

} if(***==0)//如果沒有被打上標記

prime[i]=1;//prime來標記這個數是否為素數。

}

這樣的時間複雜度為近似 \(o(n\sqrt)\)。

我們發現,上面兩種篩法會篩到許多沒有意義的數,所以我們必須換一種思想方式。

埃氏篩,就是先將 \(prime\) 陣列全部賦值為 \(1\)。(記得將 \(prime_1\) 賦值為 \(0\) )。

仍然是要從 \(1\) 列舉到 \(n\) 。我們先假設當前列舉到了 \(i\) 。

如果 \(prime_i=1\) 也就是 \(i\) 為質數,則我們可以知道 \(i\) 的倍數均為合數,所以我們就將 \(prime_\) 賦值為 \(0\) 。

最終篩完之後,如果 \(prime_i=1\) , \(i\) 就是質數。

關鍵**

memset(prime,1,sizeof(prime));

priem[1]=0;

for(int i=1;i<=n;++i)

}

這樣的時間複雜度為 \(o(nlognlogn)\)。

我們發現,埃氏篩已經很快了,但是還是有所不足。

因為在埃氏篩中,有很多數有可能被篩到很多次(例如 \(6\) , 他就被 \(2\) 和 \(3\) 分別篩了一次)。 所以在尤拉篩中,我們就是在這個問題上面做了優化,使得所有合數只被篩了一次。

首先,我們定義 \(st_i\) 陣列表示 \(i\) 是否為質數,\(primes_i\) 儲存已經找到的所有質數,\(cnt\) 儲存當前一共找到了多少質數。

如果當前已經列舉到了 \(i\) 。如果 \(st_i=1\) ,也就是 \(i\) 為素數。則 \(primes_=i\)。

然後我們每一次列舉都要做這個迴圈: 列舉 \(j\) 從 \(1\) 到 \(cnt\)。\(st_=0\)(因為 \(primes_j\) 為素數,\(i\) 就表示這個素數的多少倍,要把他篩掉)。

注意,接下來是重點!如果 \(i\mod primes_j=0\),跳出第二層迴圈。(因為尤拉篩預設每乙個合數只能由他的最小質因數篩去,而滿足以上條件之後,\(primes_j\) 就不是這個數字的最小質因數了,所以我們跳出第二層迴圈)。 因此,有了這一層優化之後,每乙個合數就只能被篩掉一次了。

關鍵**

memset(st,0,sizeof(st));

st[1]=0;

for(i=2;i<=n;i++)

}

這樣的時間複雜度為 \(o(n)\)。

以上就是我要講的質數篩演算法了,希望對大家有所幫助。

演算法 質數,質因數,篩質數

質數在大於1的整數中,如果只包含1和本身這兩個約數,就被稱為質數,或者叫素數。有3中形式 由於sqrt 計算較慢。不推薦 bool is prime int n 由於i i有可能會大於n,而當n較大時,可能會爆int,從而成為負值。不推薦 bool is prime int n 推薦 試除法 boo...

質數 篩質數

質數定理 1 n中質數有n ln n 個質數 按順序刪除每個數的倍數,最後剩下的就是質數。給定乙個正整數n,請你求出1 n中質數的個數。輸入格式 共一行,包含整數n。輸出格式 共一行,包含乙個整數,表示1 n中質數的個數。資料範圍 1 n 1061 n 106 輸入樣例 8輸出樣例 4 includ...

演算法 線性篩質數

輸出從0 00到1000000 1000000 100000 0的所有質數。首先0 00和1 11不是質數,從2 22開始逐個判斷是否為質數。如果t tt為質數,那麼對於任意正整數k kk,k t k times t k t不是質數,因此可以將k t k times t k t篩去。如果t tt已經...