尤拉篩法是用線性時間求取給定範圍內的素數的個數,當然素數的值也是可以記錄的,適用於大範圍性的素數求取,如果只是判斷某乙個素數,尤拉篩就顯得大材小用了(費空間資源),這時候可以考慮miller-rabin 素數測試。
尤拉函式的時間複雜度趨於o(n)的,即使是1e8也不在話下
講解尤拉篩之前回顧一下埃拉託斯特尼篩法
埃拉託斯特尼篩法:原理就是先找出乙個素數然後把這個素數的倍數都標記為合數(乙個正整數的所有倍數一定是合數,除了1),在下一次遇到被標記的數時直接跳過。
例如:第一次遍歷遇到素數2,所以(4,6,8,10…)被標記為合數
第二次遍歷遇到素數3,所以(9,12,15…)被標記為合數
第三次遍歷遇到合數4,因為已經被2的倍數標記所以直接跳過。
然後按照上面方法一直遍歷到最後就篩選出了所有素數
…**
#include
#include
#include
using
namespace std;
int prime[
1000000];
/*埃拉託斯特尼篩法*/
bool vis[
100000001];
//1表示訪問過,0表示沒有訪問過
intmain()
}}printf
("%d"
,prime[0]
);return0;
}
注意:上面是我對埃拉託斯特尼篩法做了一定修改,便於後面理解尤拉篩。(望dalao勿吐槽)
但是埃拉託斯特尼篩法的時間複雜度o(nlognlogn)顯然對於1e8的資料是會超時的,其實篩選的過程中做了重複的操作,比如12這個數是2的倍數,也是3的倍數,就被2和3的倍數標記了兩次,後面較大的數被重複標記的次數更多,為了解決重複標記的問題,於是尤拉篩排上用場了。
先上**,方便講解
#include
#include
using
namespace std;
const
int maxn=
1e8+1;
const
int inf=
1e6;
int prime[
100000];
//存素數
bool vis[
100000001];
//0代表沒有訪問過,1訪問過
intmain()
for(
int j=
1;j<=prime[0]
&&i*prime[j]
<=n;j++
)//以i為倍數進行篩除,對所有已知素數的倍數(也就是合數)
}printf
("%d"
,prime[0]
);return0;
}
首先解釋為什麼要j從1開始並且j<=prime[0]
原因:因為我們要對每乙個已求出來的素數的倍數標記為合數,倍數為i,因為i會一直從2到n。
說到這裡有人會問,怎麼確定它就能保證不重複標記合數
這就是我們這裡if(i%prime[j]==0) break;
的作用,如果不退出迴圈當我們繼續遍歷到i*prime[j+1]的時候,因為i%prime[j]=0,故i=t倍prime[j],所以i*prime[j+1]=t * prime[j] * prime[j+1],相當於是prime[j]的倍數(已經被標記過),所以這樣就會造成重複標記,因此我們跳出迴圈。
不會重複標記我們已經證明了
接下來有乙個很頭痛的事情就是你怎麼知道不會遺漏標記呢?(我也是想了很久,才明白,本蒟蒻太痛苦了)
舉個例子:在遍歷標記合數是prime[3]也就是5是從==i=5(5的5倍開始)==開始標記的(prim[j]的倍數標記始終是從i=prime[j]開始的,也就是i>=prime[j]),那麼5的四倍,三倍,兩倍不就沒有標記到嗎?
(其實一點就通)分析:我們知道任何乙個正整數都是可以由若干個素數的冪次的乘積構成(質因數分解),所以如果i其他更小的素數的倍數,所以已經被標記,故我們不需要再次標記,所以這樣就能夠解釋上面素數5的例子了。
趁熱打一下鐵吧
洛谷 p3912 素數個數
如果有分析不對的地方,還望dalao指出
尤拉函式尤拉篩
尤拉函式求小於等於n與n互質的數的個數 複習時發現這個知識點竟然沒有整理 n為素數即為n 1 除了其本身 n為素數的倍數 ola sushu j i ola i sushu j else ola sushu j i ola i sushu j 1 include include include in...
線性篩求尤拉函式的證明
若 i 為質數,則 varphi i i 1 若 p j mid i 則 varphi i times p j varphi i times p j 若 p i nmid i 則 varphi i times p j varphi i times varphi j varphi i times p ...
線性篩(尤拉篩)
昨天的考試跪的一塌糊塗 第一題水過,第二題帶wa的樸素,最後題忘了特判左端點全跪,分數比起預計得分整整打了個對折啊!步入正題 線性篩 尤拉篩 一般的篩法 ppt裡叫埃拉託斯特尼篩法,名字異常高貴 的效率是o nlglgn 其實很接近o n 啊!對於一些例如n 10000000的殘暴資料會跪,於是,線...