洛谷p1835 素數密度 (線性尤拉篩,埃式篩)

2021-10-04 21:32:23 字數 1769 閱讀 4322

題目分析

難度:普及+/提高

暴力40分做法:從l到r進行列舉,然後判斷是否為素數!

但這樣顯然是不對的,要結合篩法來解決此題,雖然l,r的範圍是整個int的取值,但是兩者的差值為1e6,可以從此突破!

預備知識 (解決乙個問題:求出不大於n的素數的個數)

樸素篩法:時間複雜度 o(n根號n)

//普通樸素演算法 求質數  ( n根號n的時間複雜度 ) 

void

or_prime

(int n)}if

(flag==

0) prime[

++cnt]

= i;

}}

埃拉託斯特尼篩法 時間複雜度: o(nloglogn)

要得到自然數n以內的全部素數,必須把不大於的所有素數的倍數剔除,剩下的就是素數。

給出要篩數值的範圍n,找出以內的素數。先用2去篩,即把2留下,把2的倍數剔除掉;再用下乙個質數,也就是3篩,把3留下,把3的倍數剔除掉;接下去用下乙個質數5篩,把5留下,把5的倍數剔除掉;不斷重複下去…。

bool isprime[n]

;int prime[n]

;void

er_prime

(int n)}}

}

尤拉線性篩 時間複雜度: o(n)在埃氏篩的基礎上,保證每乙個合數只被篩選一次!!!

//尤拉篩法 

void

euler_prime

(int n)

}}

有了篩法的基礎,那麼接下來的思想就是找出所有位於【2,sqrt(r)】 之間的所有素數,然後用這些素數的倍數來篩掉[l,r]之間的所有合數。

假設現在的某乙個素數為p,現在要找的值是大於等於l的第乙個p的倍數 num

當l>p時,

如果l%p==0,則num=l;

如果p不能整除l,num=ceil(l/p)*p; ceil(l/p)=floor((l+p-1)/p)=(l+p-1)/p

當l<=p,則num = 2*p(因為p是素數,不能從p開始)

注意ceil的返回值型別為double,小心數值溢位!!!

ac**

#include

using

namespace std;

typedef

long

long ll;

bool isprime[

50000

+100];

int cnt;

int prime[

10000+10

];//尤拉篩法

void

euler_prime

(int n)}}

bool vis[

1000000+10

];intmain()

int ans=0;

for(ll i=

1;i<=r-l+

1;i++)if

(vis[i]==0

) ans++

; cout<

}

P1835 素數密度 尤拉篩 埃氏篩法

題目描述 給定區間 l,r l r 2147483647,r l 1000000 請計算區間中素數的個數。輸入格式 兩個數l和r。輸出格式 一行,區間中素數的個數。輸入輸出樣例 輸入 1 2 11 輸出 1 此題有乙個坑。若乙個數是int max,看起來用int是可以的。但若是把這個數 1了呢?in...

尤拉篩選素數(洛谷p1217)

int prime 60000005 bool tag 100000005 memset tag,0,sizeof tag int cnt 0 tag 0 tag 1 1 for int i 2 i prime儲存所有素數,用來列舉最小質因子 tag判斷數字是否為質數,0為質數。注意本題因為記憶體限...

洛谷 P3383 篩素數 尤拉篩素數模板

如題,給定乙個範圍n,你需要處理m個某數字是否為質數的詢問 每個數字均在範圍1 n內 輸入格式 第一行包含兩個正整數n m,分別表示查詢的範圍和查詢的個數。接下來m行每行包含乙個不小於1且不大於n的整數,即詢問概數是否為質數。輸出格式 輸出包含m行,每行為yes或no,即依次為每乙個詢問的結果。樣例...