ps:證明**神牛部落格。
#include
#include
using
namespace
std;
const
int n=100100;
int v[n],p[n],n,m,tot;
int main()
}
}
首先,先明確乙個條件,任何合數都能表示成一系列素數的積。
不管 i 是否是素數,都會執行到「關鍵處1」,
①如果 i 都是是素數的話,那簡單,乙個大的素數 i 乘以不大於 i 的素數,這樣篩除的數跟之前的是不會重複的。篩出的數都是 n=p1*p2的形式, p1,p2之間不相等
②如果 i 是合數,此時 i 可以表示成遞增素數相乘 i=
p1∗p
2∗..
.∗pn
p_i都是素數(2
≤i≤n
),pi
≤pj(
i≤j)
p1 是最小的係數。
根據「關鍵處2」的定義,當p1
==pri
me[j
] 的時候,篩除就終止了,也就是說,只能篩出不大於p1
的質數*i。
我們可以直觀地舉個例子。i=2*3*5
此時能篩除 2*i ,不能篩除 3*i
如果能篩除3*i 的話,當 i』 等於 i』=3*3*5 時,篩除2*i』 就和前面重複了。
需要證明的東西:
乙個數會不會被重複篩除。
合數肯定會被乾掉。
根據上面」只能篩出不大於p1的質數*i」的條件,現在分析乙個數會不會被重複篩除。
設這個數為 x=p1*p2*…*pn, pi都是素數(1<=i<=n) , pi<=pj ( i<=j )
當 i = 2 時,就是上面①的情況,
當 i >2 時, 就是上面②的情況, 對於 i ,第乙個能滿足篩除 x 的數 y 必然為 y=p2*p3…*pn(p2可以與p1相等或不等),而且滿足條件的 y 有且只有乙個。所以不會重複刪除。
證明合數肯定會被乾掉? 用歸納法吧。
模擬乙個模型,比如說我們要找出 n 中2個不同的數的所有組合 ,1<=i<=n, 1<=j<=n,
我們會這麼寫
for (i=1; i
i ) for (j=i+1; j
<=n; ++j)
我們取 j=i+1 便能保證組合不會重複。快速篩法大概也是這個道理,不過這裡比較難理解,沒那麼直觀。 素數篩法(素數篩 線性篩)
求素數的方法在現階段可以總結為三種 這種方法最為簡單但效率太低,經過優化時間複雜度最低是o n sqrt n 輸入乙個n,輸出n以內所有素數 include intprime int n if flag 0 優化 printf d i intmain 素數篩法原理 2是素數,那麼2的所有倍數都是合數...
線性篩素數
如題,給定乙個範圍n,你需要處理m個某數字是否為質數的詢問 每個數字均在範圍1 n內 輸入格式 第一行包含兩個正整數n m,分別表示查詢的範圍和查詢的個數。接下來m行每行包含乙個不小於1且不大於n的整數,即詢問該數是否為質數。輸出格式 輸出包含m行,每行為yes或no,即依次為每乙個詢問的結果。in...
線性素數篩
兩個星期之前,如果你讓我篩一下素數,我會告訴你很簡單,然後一頓敲 define size 1000000 int main int pos int flag for int i 2 i size i if flag 1 printf 2f double clock clocks per sec re...