題目分析
難度:普及+/提高
暴力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,即依次為每乙個詢問的結果。樣例...