素數篩法(適用於較大數且不超時)思路 答案和注釋

2021-08-09 10:44:58 字數 1652 閱讀 4142

用篩法求[a,b]中的素數。

find out the prime numbers in [a, b].

#include

int main()

for(i=2;i<=1000;i++)}}

}for(i=a;i<=b;i++)

}

以上是用於求1到1000內素數的最原始的篩法。如果把範圍擴大到1到100,000,000,顯然陣列長度會很大而且會出現很多不必要的運算和遍歷過程。

經過思考,我主要找到兩處可以進行優化的地方。

1.假設要求10000以內的素數,因為100*100=10000,100以內的質數就足以篩掉範圍內所有合數,這樣100到10000的數沒有必要作為因數再遍歷一次。

2.按照上面這種方法,即使a和b的範圍很小或者取值都很小,還是需要將1到100,000,000的所有素數都求出來再輸出,程式幾乎不隨a和b取值不同變化。

由此,我想到了如何改進這兩個地方。

將函式分為兩部分。第一部分利用篩法求1到b的平方根的全部素數。解決了第乙個問題的同時,也使程式和b的取值建立了聯絡。第二部分利用篩法和上一步求出的素數篩出a到b內的全部合數。

#include

#include//後面要用到sqrt函式,數學函式定義在數學庫中,標頭檔案為math.h

int main()

int prime[10001],num=0;//定義新陣列,將1到b的平方根內的所有素數存到prime陣列中

for(i=2;i<=m;i++)}}

}//第一部分結束,只有prime陣列和num下一步還要用到。

int d[260001],count=1;//d的長度為a和b的最大差值

for(j=a;j<=b;j++)

//用2這個肯定存在於所有情況中的素數初始化表示a到b之間數的陣列d

//對於後面篩除a,b間所有合數這一步,需要用到的主要資料只有:作為因數的prime陣列和要被判斷的d陣列

for(i=2;i<=num;i++)

//直接跳過已經被篩除的數,減少重複運算

if(d[count]%prime[i]==0&&d[count]/prime[i]!=1)

//將能被當前prime[i]整除的數篩除,標記為0

else

count++;

} }

for(i=1;i<=(count-1);i++)

}//輸出所有沒有被標記為0的數即為素數

}

一些容易出現bug的地方:

1.注意要特殊討論1

2.count、i記數;有的時候退出迴圈前會加1,想得到的數就比輸出的少1

3.注意if,else if,else的關係;如果是if,if,else並列,如論如何都會進入else。

4.除錯時可以用1-10,90-100這兩組資料。90-100第

一、二部分都只迴圈十次。

根據這道題,我得出了一點經驗:

1.篩法中乙個重要的思想是「標記」,把陣列中某個數標記為乙個特定的值來表示這個數具有某種性質。

2.在迴圈中可以用continue跳過一些被標記的數,簡化運算。

3.可以定義一些新陣列/變數儲存有用的資料,使程式更加清晰。

素數篩法(素數篩 線性篩)

求素數的方法在現階段可以總結為三種 這種方法最為簡單但效率太低,經過優化時間複雜度最低是o n sqrt n 輸入乙個n,輸出n以內所有素數 include intprime int n if flag 0 優化 printf d i intmain 素數篩法原理 2是素數,那麼2的所有倍數都是合數...

多執行緒適用於阻塞式IO場景,不適用於平行計算場景

python的標準實現是cpython。cpython執行python 分為2個步驟 首先,將文字原始碼解釋編譯為位元組碼,然後再用乙個直譯器去 解釋執行位元組碼。位元組碼直譯器是有狀態的,需要維護該狀態的一致性,因此使用了gil global interpreter lock,全域性直譯器鎖 gi...

折半查詢法(僅適用於已排好順序)

includeusing namespace std templateint binarysearch type array,int lenght,type key 不適用於char 型別 array mid key right mid 1 left mid 1 return 1 int main ...