數論基礎 埃氏篩法 區間篩法(模板)

2021-10-03 08:59:05 字數 1620 閱讀 3381

區間篩法

求n之前的所有素數

原理

1.如果採用利用文章中第乙個o(sqrt(n))的演算法,進行n次迴圈即可得到答案。顯然,這樣o(nsqrt(n))肯定超時,所以我們需要進行優化。

2.如果我們判斷出a是素數,那麼我們就可以確定a的倍數都是合數。因此可以將這些倍數刪除,這樣就可以去掉一些不必要的判斷。

3.進一步,我們會發現有些合數我們進行了多次刪除。例如:對於合數6,它是2的倍數,也是3的倍數,所以我們進行了兩次刪除,因此我們可以進一步優化。

我們需要確保每乙個合數只能被最小質因子篩掉。這一步我們通過核心**if(i%prime[j]==0)break;實現。(在**之後解釋)

**
#define maxn 100000100 

int num[maxn]

;int prime[maxn]

;//儲存得到的素數 ,但是prime[0]是記錄素數個數

intget_prime()

}}

注釋
if

(i%prime[j]==0

)break

;//如果i%prime[i]==0滿足,

//則代表i*prime[j+1]能夠用乙個更小的素數和更大的合數相乘得到,因此跳出迴圈

//可以理解為ab%a==0,所以ab*c(a//例如:當i=6時,num[6*2]=1,而6%2=0,所以有6*3=18=9*2

另乙個模板

來自kuangbin的模板,用乙個陣列,節省了空間,但難度大一點

const

int maxn =

1e7+5;

void

getprime()

}}

求[a,b]中的素數

原理

1.首先明確:b以內的所有合數的最小質因數一定不會大於b

\sqrt

b​。證明:

設s的最小質因數a

>

ba>\sqrt

a>b​

,則s>=a*a>b。與條件矛盾。

2.通過[2,

b)

[2,\sqrt)

[2,b​)

的素數表,把埃氏篩法用到[a,b)上。

也就是說,從[2,

b)

[2,\sqrt)

[2,b​)

篩得素數得同時,也將它得倍數從[a,b)刪去。最後就只剩下[a,b)中得素數了。

**
typedef

long

long ll;

int is_prime_1[maxn]

;int is_prime_2[max_sqrt_b]

;void

segment_sieve

(ll a,ll b)

for(ll j=

max(

2ll,

(a+i-1)

/i)*i;j=i)//篩[a,b]; j的初始值是在[a,b)中i的最小倍數;2ll表示2是longlong 型別}}

}

數論 埃氏篩法

這學期的離散數學課程學了一點初等數論,其中的埃氏篩法當時課上沒有太懂,課後看了 挑戰程式設計競賽 一書終於弄懂了。這本書確實很好!演算法簡潔優美。如果只對乙個整數進行素性測試,通常o n 的演算法就足夠了。但如果要對許多整數進行素性測試,則有更為高效的演算法,其中就包括埃拉託斯特尼篩法,簡稱埃氏篩法...

埃氏篩法 素數篩

埃式篩法 給定乙個正整數n n 10 6 問n以內有多少個素數?做法 做法其實很簡單,首先將2到n範圍內的整數寫下來,其中2是最小的素數。將表中所有的2的倍數劃去,表中剩下的最小的數字就是3,他不能被更小的數整除,所以3是素數。再將表中所有的3的倍數劃去 以此類推,如果表中剩餘的最小的數是m,那麼m...

素數篩法(埃氏篩,線性篩)

時間複雜度o nloglogn void prime int b prime i 1則是合數 原理很簡單,所有合數可以表示為乙個質數跟另乙個數的積,列舉每個已知素數的倍數就能標記完。但很明顯,這樣做會有重複。比如12 3 4 2 6,在2這個素數進行倍數標記時會標記,在3這個素數進行倍數標記時同樣會...