依次列舉每個數判斷其是否為素數,複雜度過高,且整個過程顯得粗暴而不具有技巧性。下面提出一種更好的辦法解決該問題。
首先考慮這樣乙個命題:若乙個數不是素數,則必存在乙個小於它的素數為其因數。這個命題顯然是正確的。假如已經獲得了小於乙個數的所有素數,只需確定該數不能被這些素數整除,這個數即為素數。但是這樣依然需要大量的列舉測試工作。可以換乙個角度,在獲得乙個素數時,即將它的所有倍數標記為非素數,這樣當遍歷到乙個數時,它沒有被任何小於它的素數標記為非素數,則確定其為素數。按照如下步驟完成工作:
從2開始遍歷2到1 0000的所有整數,若當前整數沒有因為它是某個小於其的素數的倍數而被標記成非素數,則判定其為素數,並標記它所有的倍數為非素數。然後繼續遍歷下乙個數,直到遍歷完2到1 0000區間內所有的整數。此時,所有沒被標記成非素數的數字即為要求的素數。這種演算法被稱為素數篩法。
#include int prime[10000];//儲存篩得的素數
int primesize;//儲存的素數個數
bool mark[10001];//若mark[x]為true,則表示該數x已被標記成非素數
void init()//初始化,所以數字均沒被標記
primesize=0;//得到的素數個數為0
for(int i=2;i<=10000;i++)
}}int main()
{ init();//在程式一開始首先取得2到10000中所有素數
int n;
while(scanf("%d",&n)!=eof){
bool isoutput=false;//表示是否輸出了符合條件的數字
for(int i=0;i=n)break;
if(prime[i]利用素數篩法,在處理輸入的數字前,先處理出2到10000區間內所有素數。當輸入n時,則依次比較已經得到的素數是否符合返回條件。若符合則輸出,否則繼續比較下乙個素數。
篩法中使用了乙個技巧。當判定i為素數,要標記其所有倍數為非素數時,並沒有從2i開始標記,而是直接從ii開始標記。因為ik(kk同時也是k的素因數的倍數。所以這裡直接從i的平方開始標記起。盡可能避免重複工作也是程式優化的一大思路。
使用乙個bool變數表示是否已經輸出符合條件的數字。有兩個目的,其一保證了除第乙個輸出的數字外,其他數字輸出時均在其前附加乙個空格,以達到題目要求的輸出數字之間存在空格而最後乙個數字後沒有空格的要求。其二,作為判斷依據使在不存在符合條件的素數時,按題目要求輸出-1。
素數篩法通常作為程式真正開始處理輸入資料前的預處理使用,即預先處理出相關區間內的所有素數,以備後續工作使用。
例4 7 素數 九度教程第51題(素數篩法)
依次列舉每個數判斷其是否為素數,複雜度過高,且整個過程顯得粗暴而不具有技巧性。下面提出一種更好的辦法解決該問題。首先考慮這樣乙個命題 若乙個數不是素數,則必存在乙個小於它的素數為其因數。這個命題顯然是正確的。假如已經獲得了小於乙個數的所有素數,只需確定該數不能被這些素數整除,這個數即為素數。但是這樣...
質因數的個數 九度教程第54題
對乙個數x分解素因數即確定素數p1,p2 pn,使其滿足下式 必要時還要確定e1,e2等冪指數。本題即求e1,e2,en的和。利用素數篩法預先篩選出所有可能在題面所給資料範圍內成為素因數的素數。並在程式輸入待處理數字n時,依次遍歷所有小於n的素數,判斷其是否為n的因數。若確定某素數為n的因數,則通過...
統計同成績學生人數 九度教程第10題
將儲存位置與資料本身對應起來的儲存手段就是hash,使用hash解決此類問題。這類問題存在乙個共同特點 輸入的分數種類是有限的。可以看到,輸入的分數不僅嚴格在0到100的區間之內,同時它又一定是乙個整數。這樣,輸入的資料一共只有101種可能,只要為這101種可能分別計數,便能在輸入結束時便得知每一種...