深入理解線性質數 素數 篩

2021-10-04 14:44:00 字數 1861 閱讀 6566

int p[n]

, cnt;

//p[n]用來存質數,cnt表示質數的個數

bool st[n]

;//表示當前的數有沒有被篩過

樸素篩法 o(n

logn

)o(nlogn)

o(nlog

n)

void

get_primes

(int n)

由於當執行到 i 時可以確保已經用小於 i 的每乙個質數都篩過一遍,因此可以保證每乙個合數都會被篩掉

埃式篩法 o(n

logl

ogn)

o(nloglogn)

o(nlog

logn

) 在樸素篩法中,2 * 4 與 4 * 2 的結果都是8,因此乙個數可以用合數篩的時候,其實已經被質數已經篩過一次,所以可以只在 i 是素數的時候篩

void

get_primes

(int n)

}

由算術基本定理知一定可以將每乙個合數都篩掉(因為每乙個合數都能分成若干個質數)

線性篩法 o(n

)o(n)

o(n)

, n = 1e7時基本上就比埃式篩法快一倍

演算法核心:保證每個合數只會被其最小質因子篩掉

void

get_primes

(int n)

}

首先證明合數是不是一定會被篩掉

假設n是乙個合數,且p是n的最小質因子

故 有n

=p∗n

p故有n = p * \frac

故有n=p∗

pn​只需要滿足p小於n

p\frac

pn​,當 i 等於n

p\frac

pn​時,n就會被篩掉

反證法,假設n

p\frac

pn​小於p

如果n

p\frac

pn​是質數,那麼n

p\frac

pn​就是n的最小質因子,故n

p\frac

pn​小於p不成立

如果n

p\frac

pn​是合數,那麼由算術基本定理,n

p\frac

pn​一定可以分出乙個比p小的素數來作為n的最小質因子,故n

p\frac

pn​小於p不成立

綜上,p一定小於n

p\frac

pn​,故每乙個合數肯定會被篩掉

其次證明是不是每個合數只會被其最小質因子篩掉

for

(int j =

0; p[j]

* i <= n; j ++

)

如果 i % p[ j ] == 0 說明p[ j ]是 i 的最小質因子(因為p[ j ]是從小到大列舉的), 所以p[ j ]也是 i * p[ j ]的最小質因子

如果 i % p[ j ] != 0 說明p[ j ]小於 i 的所有質因子(因為p[ j ]是從小到大列舉的),所以p[ j ]也是 i * p[ j ]的最小質因子

而至於為什麼要break,因為一旦 i % p[ j ] 為0時,說明p[ j ]是 i 的最小質因子,而此時如果繼續迴圈下去,用p[ j + 1 ] * i 篩時,由於 i 的最小質因子p[ j ]小於p[ j + 1],因此這時候被篩掉的合數就不是被他的最小質因子篩掉的了

所以break也是保證線性篩法時間複雜度的乙個重要原因~

深入理解線性素數篩 以後再也不用模板了

線性素數篩也算是一種基本的演算法吧,和揹包一樣,必須要做到深入理解其原理,並且能快速打出 來。兩個大前提 1.自然數中,1既不是素數也不是合數。小學知識 2.乙個合數一定能分解成乙個素數和另乙個數相乘。這個我不能證明,但是科學應該不會有錯 先從普通的思路談起。如果問你乙個數是不是素數,那你一定是fo...

找素數(質數) 線性篩法和埃氏篩法

先看這道題 洛谷p1217回文質數 對於這道題,普通的暴力模擬會tle,所以得尋求改進。這裡我學會了兩種方法 第一種 線性篩法 這種演算法的核心思想就是 任何乙個合數都可以由質數相乘得到 下面就是核心 吃透了核心 就可以在其中新增點細節,然後就可以拿去解決問題了 這裡需要開多大的陣列取決自己 boo...

小X的質數 NOIP模擬賽 魔改線性篩素數

題意 求 l r 範圍內是質數或兩個質數乘積的數的個數 魔改線性篩素數即可,預處理1 nmax的所有符合要求的數的數量,對於每組詢問 o 1 回答。對於每個素數,肯定是要計算的。在後面排除合數的時候,判斷當前數是不是素數,若是,也算入其中。用字首和優化,對於一組詢問 l,r 回答 cnt r cnt...