可以先來看看一道簡單的題目:
試列印 1 - n 範圍內的素數表。
分析:
好,我們從1~n進行列舉,判斷每個素數是否是素數,如果是素數,則加入素數表。那麼這個演算法的時間複雜度是多少呢?可以看到,列舉部分的複雜度是o(n),而判斷素數的演算法是o(n^1/2),因此總複雜度是o(n * n ^1/2)。但是顯然這個複雜度對n超過10 ^ 5的情況來說是有問題的。因為對一般的oj系統來說,一秒能承受的運算次數大概是10 ^ 7 ~ 10 ^ 8,而程式一般要求1s內進行。自己可以估算一下。
給出**(以求解100以內的所有素數為例):
#include
#include
bool
isprime
(int n)
return
true;}
int prime[
101]
,pnum =0;
//prime陣列存放素數,pnum為陣列下標
bool p[
101]=;
void
find_prime()
}}intmain()
}
好,我們接著上面講的繼續講下去,既然樸素演算法的時間複雜度不是很令人滿意,那麼是否有更好的演算法呢?
「埃氏篩法」就是眾多篩法中簡單的一種,可以達到o(nloglogn)的時間複雜度。所謂「篩法」關鍵就在於乙個篩字。從小到大列舉所有數,對每乙個素數,篩去它的所有倍數,剩下的都是素數了。這聽起來好像是在逗人???你還不知道哪個數是素數呢,簡直就是悖論。
先來看乙個例子吧:求1~15中的所有素數。
分析:
至於「篩」這個動作的實現,可以使用乙個bool型陣列p來標記,如果a被篩掉,那麼p[a]為true,否則,p[a]為false。在程式開始時可以初始化p陣列為false。
給出上述題目的**(埃氏篩法):
#include
const
int maxn =
101;
int prime[maxn]
, pnum =0;
bool p[maxn]=;
//初始化p陣列全部為false,如果a被篩掉,那麼p[a]為true;否則,p[a]為false
void
find_prime()
}}}int
main()
}
令pi表示第 i 個素數,現任意給兩個正整數m<=n<=10^4,請輸出pm到pn的所有素數。
輸入格式:
輸入在一行中給出m和n,其間以空格分隔。
輸出格式:
輸出從pm~pn的所有素數,每10個數字佔一行,其間以空格分隔,但行末不能有空格。
給出**(埃氏篩法和樸素都可以,這裡給出的是埃):
//埃氏篩法
#include
const
int maxn =
1000001
;int prime[maxn]
, num =0;
bool p[maxn]=;
//初始化p陣列全部為false,如果a被篩掉,那麼p[a]為true;否則,p[a]為false
void
find_prime
(int n)}}
}int
main()
return0;
}
埃氏篩法 素數篩
埃式篩法 給定乙個正整數n n 10 6 問n以內有多少個素數?做法 做法其實很簡單,首先將2到n範圍內的整數寫下來,其中2是最小的素數。將表中所有的2的倍數劃去,表中剩下的最小的數字就是3,他不能被更小的數整除,所以3是素數。再將表中所有的3的倍數劃去 以此類推,如果表中剩餘的最小的數是m,那麼m...
素數 埃氏篩法
題目 求2 100以內的素數。素數 prime number 又稱質數,是指乙個大於1的自然數,除了1和它本身外,不能被整除以其他自然數。解法一 根據素數的定義,即用該數除比其小的數 1除外 都不能除盡,即為素數 public class prime if i n system.out.print ...
快速求素數表 埃氏篩法與尤拉篩法
尤拉篩法 素數的定義 素數就是除了1和本身之外沒有其他的約數,所以有約數的都不是素數。因此,埃氏篩法的思想就是 先去掉2的倍數,再去掉3的倍數,再去掉4的倍數,依此類推,直到最大數小於最後乙個標出的素數的平方,那麼剩下的序列中所有的數都是素數。o nloglogn 時間複雜度的證明戳此鏈結 incl...