判斷素數方法(二)
阿新 • • 發佈:2019-01-10
效率 out 用處 感覺 sin i++ 大於 urn 優化 ,直接上代碼吧
判斷素數的方法(二)
前面那篇文章寫了素數的判斷方法,現在講下如何在區間中篩選出全部素數。
方法一
既然已經可以判斷素數了,自然可以通過判斷素數的方法來依次判斷素數,從而進行篩選,請原諒我的表述能力,代碼如下
#include<bits/stdc++.h> using namespace std; inline int prime(int x) { for (int i = 2; i <= sqrt(x); i++) if (x%i == 0) return 0; return 1; } int main() { int left, right; cin >> left >> right; for (int i = left; i <= right; i++) if (prime(i) == 1) cout << i << " "; }
但這個時間復雜度好像有點高,假設從[100,500]這個區間,要執行1878次,執行判斷的復雜度是O(sqrt(n)),外循環是O(n),所以總復雜度是O(n*sqrt(n)),其實效率並不高,讓我們想辦法優化下...
方法二
這個方法我高中自己莫名其妙來的靈感,哦豁,有點小驕傲,思考下素數的定義:質數定義為在大於1的自然數中,除了1和它本身以外不再有其他因數 ,反正百度是這麽寫的qaq,那麽換句話說,只要是除1意外任何數字的倍數就一定不是素數了,比如2,2的倍數是4,6,8,10,等等,那就一定不是素數了,3的倍數6,9,12,一定不是素數了。
這有什麽用處呢。感覺一切描述都是蒼白的,好吧,其實是我不會描述
#include<bits/stdc++.h> using namespace std; const int MAXV = 10001; int XX[MAXV]; void init(int left, int right) { for (int i = 2; i <= right; i++) { int k = 2; while (i*k <= right) { XX[i*k] = 1; k++; } } for (int i = left; i <= right; i++) if (!XX[i]) cout << i << " "; } int main() { int myleft, myright; cin >> myleft >> myright; init(myleft,myright); }
我們接著假設[100,500]這個區間,看看他到底執行多少次,2192次。
什麽2192次,那不是比上面那個還高麽,讓我們把數據區間放大一點..[100,9999]試下,73647次,而上面那個算法需要117291次,隨著數據增大,優勢越來越明顯,其實我們還可以優化上面那個篩選算法。
試想一下4這個數字,他已經被2篩選了,這就意味這4的倍數也一定是2的倍數,那麽後面4的倍數這個循環就不用做了,讓我們試試,先付下代碼
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 10001;
int XX[MAXV];
int mycount= 1;
void init(int left, int right)
{
for (int i = 2; i <= right; i++)
{
if(XX[i]==1)
continue;
int k = 2;
while (i*k <= right)
{
XX[i*k] = 1;
k++;
}
}
for (int i = left; i <= right; i++)
if (!XX[i])
cout << i << " ";
}
int main()
{
int myleft, myright;
cin >> myleft >> myright;
init(myleft,myright);
cout << endl;
cout << mycount;
}
代碼很簡單,在篩素數的前面加個判斷就行。讓我們測試下運行次數,哇23070次,這真的是一個偉大的改進。速度翻了一番還多。
其實這個算法很早就有了,反正叫啥我布吉島
先就這樣吧~~~~~
判斷素數方法(二)