tag 素數 數論
素數總是乙個比較常涉及到的內容,掌握求素數的方法是一項基本功。
基本原則就是題目如果只需要判斷少量數字是否為素數,直接列舉因子2 。。n^(0.5) ,看看能否整除n。
如果需要判斷的次數較多,則先用下面介紹的辦法預處理。
首先先介紹一般的線性篩法求素數
[cpp]view plain
copy
void
make_prime()
return
; }
這種方法比較好理解,初始時,假設全部都是素數,當找到乙個素數時,顯然這個素數乘上另外乙個數之後都是合數(注意上面的 i*i , 比 i*2 要快點 ),把這些合數都篩掉,即演算法名字的由來。
但仔細分析能發現,這種方法會造成重複篩除合數,影響效率。比如10,在i=2的時候,k=2*15篩了一次;在i=5,k=5*6 的時候又篩了一次。所以,也就有了快速線性篩法。
快速線性篩法沒有冗餘,不會重複篩除乙個數,所以「幾乎」是線性的,雖然從**上分析,時間複雜度並不是o(n)。先上**
[cpp]view plain
copy
#include
using
namespace
std;
const
long
n = 200000;
long
prime[n] = ,num_prime = 0;
intisnotprime[n] = ;
intmain()
}
return
0;
}
首先,先明確乙個條件,任何合數都能表示成一系列素數的積。
不管 i 是否是素數,都會執行到「關鍵處1」,
①如果 i 都是是素數的話,那簡單,乙個大的素數 i 乘以不大於 i 的素數,這樣篩除的數跟之前的是不會重複的。篩出的數都是 n=p1*p2的形式, p1,p2之間不相等
②如果 i 是合數,此時 i 可以表示成遞增素數相乘 i=p1*p2*...*pn, pi都是素數(2<=i<=n), pi<=pj ( i<=j )
p1是最小的係數。
根據「關鍵處2」的定義,當p1==prime[j] 的時候,篩除就終止了,也就是說,只能篩出不大於p1的質數
*i。我們可以直觀地舉個例子。i=2*3*5
此時能篩除 2*i ,不能篩除 3*i
如果能篩除3*i 的話,當 i' 等於 i'=3*3*5 時,篩除2*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; ifor (j=i+1; j<=n; ++j)
我們取 j=i+1 便能保證組合不會重複。快速篩法大概也是這個道理,不過這裡比較難理解,沒那麼直觀。
1樓提供的方法,我整理下
//偶數顯然不行,所以先去掉偶數。可以看作上面第一種的優化吧。
//不過這種方法不太直觀,不太好理解。
[cpp]view plain
copy
我推薦這個演算法! 易於理解。 只算奇數部分,時空效率都還不錯!
half=size/2;
intsn = (
int) sqrt(size);
for(i = 0; i < half; i++)
p[i] = true
;// 初始化全部奇數為素數。p[0]對應3,即p[i]對應2*i+3
for(i = 0; i < sn; i++)
}
//素數都存放在 p 陣列中,p[i]=true代表 i+i+2 是素數。
//舉例,3是素數,按3*3,3*5,3*7...的次序篩選,因為只儲存奇數,所以不用刪3*4,3*6....
列印質數的各種演算法 裡面有個用c++模板實現的,純屬開闊眼界,不怎麼實用。
檢查素數的正規表示式 數字n用 1111。。1 (n個1)表示,純屬坑爹。
一般篩法求素數 快速線性篩法求素數
素數總是乙個比較常涉及到的內容,掌握求素數的方法是一項基本功。基本原則就是題目如果只需要判斷少量數字是否為素數,直接列舉因子2 n 0.數 5 看看能否整除n。如果需要判斷的次數較多,則先用下面介紹的辦法預處理。首先先介紹一般的線性篩法求素數 void make prime num prime 0 ...
一般篩法求素數 快速線性篩法求素數
tag 素數 數論 素數總是乙個比較常涉及到的內容,掌握求素數的方法是一項基本功。基本原則就是題目如果只需要判斷少量數字是否為素數,直接列舉因子2 n 0.5 看看能否整除n。如果需要判斷的次數較多,則先用下面介紹的辦法預處理。首先先介紹一般的線性篩法求素數 void make prime num ...
一般篩法求素數 快速線性篩法求素數
素數總是乙個比較常涉及到的內容,掌握求素數的方法是一項基本功。基本原則就是題目如果只需要判斷少量數字是否為素數,直接列舉因子2 n 0.5 看看能否整除n。如果需要判斷的次數較多,則先用下面介紹的辦法預處理。首先先介紹一般的線性篩法求素數 cpp view plain copy void make ...