在演算法競賽中經常會遇到求質數的問題,這種題目一般都是要求出一定範圍內[0,n]所有的質數或者質數的個數。最直接的思路就是根據質數的定義來判定乙個數是不是質數(即乙個數不能被除1和它本身外的任何數整除),如果我們需要對所有的數都這樣進行判斷,那麼當n非常非常大的時候,這種演算法的時間開銷就會非常大,大概為o(n^2)。這個時候就可以使用篩法來快速地求出素數,篩法求素數的基本思路就是:除了0、1之外,所有的合數都是可以表示為比它小的乙個素數的倍數,如果我們已知乙個素數,那麼我們可以把問題規定的範圍內的所有該素數的倍數全都篩除,如果該範圍內的所有的合數都被篩出,剩下的自然就都是素數了,時間複雜度大概為o(n)。
leetcode上面的一道題目:計數質數,一道典型求質數的題目,現在給出篩法求素數的解法:
class solution {
public:
int countprimes(int n) {
if(n==0||n==1)return 0;
int count=0;
bool isprime[n];//用來標記是否是素數的陣列
memset(isprime,1,sizeof(isprime));//首先假設所有的數都是素數
isprime[0]=isprime[1]=0;//0、1不是素數
for(int i=2;i因為我們的演算法相當於是從2到n遍歷一遍,我們將整個isprime陣列都初始化為1,也就是假設有的數開始都是質數,每當訪問isprime[i]的時候,如果它是合數,那麼在訪問它之前它一定已經被比它小的因子素數給篩掉了,所以在這個for(int i=2;i仔細思考一下上面的這種演算法:線性篩法雖然大大縮短了求素數的時間,但是實際上還是做了許多重複運算,比如2*3=6,在素數2的時候篩選了一遍,在素數為3時又篩選了一遍。那麼我們如何做出優化呢?如果只篩選小於等於素數i的素數與i的乘積,既不會造成重複篩選,又不會遺漏。時間複雜度幾乎是線性的。
下面給出優劃過後的篩法**:
class solution {
public:
int countprimes(int n) {
if(n==0||n==1)return 0;
int count=0;
bool isprime[n];//用來標記是否是素數的陣列
vectorsu;//用來儲存已經確定的素數
memset(isprime,1,sizeof(isprime));//首先假設所有的數都是質數
isprime[0]=isprime[1]=0;//0、1不是素數
for(int i=2;i可以看出優化之後的演算法需要額外的空間存放vectorsu來儲存已經確定的素數,所謂空間換時間,這樣的優化在剛才的基礎上又減少了不少的時間複雜度。
快速篩法求素數
stack queue的部落格 求素數是程式設計比賽中經常遇到的問題,最基本的方法是通過素數的定義直接判斷,只能被1和它本身整除的數就是素數了。這種方法適合判斷單個數是否為素數,當要求乙個範圍內素數而這個範圍又比較大時,這種方法就不太使用了,甚至程式要執行幾分鐘才能算出結果。篩法的思想是去除要求範圍...
快速篩法求素數
篩法的思想是去除要求範圍內所有的合數,剩下的就是素數了,而任何合數都可以表示為素數的乘積,因此如果已知乙個數為素數,則它的倍數都為合數。1 include2 using namespace std 3 define max 100000 4long long su max cnt 5bool isp...
素數快速求法 篩法求素數
在做題的過程中,我們會遇到一些需要求素數的要求,如果對於資料範圍很小的資料,我們有最簡單但是最耗時間的雙for迴圈巢狀法。下面舉個例子。question get the primes from 1 to 100 and print them.素數求法 基礎for迴圈法 include include...