判断素数或者求出素数的基本算法 《挑战程序设计竞赛》
2018-2-28
首先我們得明確一個概念,那就是什么是素數(shù),據(jù)我的了解,素數(shù)就是除了1和它本身之外,不存在其他的因數(shù)的數(shù)。
1.素性測試
判斷給定的數(shù)n是否是素數(shù)這應(yīng)該是最簡單的了,直接從2至n,如果存在n對其求余為0的話,那就不是素數(shù)了,這里可以降低我們的復(fù)雜度,想一下,如果一個數(shù)i是n的因子,那么n/i也必定是n的因子,不妨設(shè)i<=n/i,那么i最大的值就是sqrt(n)了,那么我們的循環(huán)也只要從2到sqrt(n)就可以了,因為這個算法比較普遍,我就不附上代碼了。
2.埃氏篩法
求出給定整數(shù)n以內(nèi)有多少個素數(shù)如果用上面的算法,那么n以內(nèi)的所有數(shù)都要進行一遍素數(shù)測試,那么時間復(fù)雜度為O(n^2),可想而知這樣的效果不是特別好。
對于2而言,2的倍數(shù)4,6,8…那就都不是素數(shù)了,
對于3而言,3的倍數(shù)6,9,12…那也都不是素數(shù)了,
如果當(dāng)前的數(shù)m是素數(shù),那么m的倍數(shù)就都不是倍數(shù)了,有的人可能會問,為什么m就是素數(shù)呢,我們想一下如果m不是素數(shù)的話,那么它一定可以表示為p*q的積,不妨我們設(shè)這里的p為素數(shù)(如果p不是素數(shù)還可以再拆,直至變?yōu)樗財?shù)),那么我們在遇到p這個素數(shù)的時候,就已經(jīng)把m,這個素數(shù)p的倍數(shù)劃掉了,所以這樣反復(fù)操作就能得到我們要的素數(shù)了。
這里的j有的人可能會想從2*i開始,其實從2*i到(i-1)*i都已經(jīng)在’i’為2到i-1的時候被計算過了,所以我們這里會選擇從i*i開始。
3.區(qū)間篩法
給定區(qū)間[a,b),求出他們兩個數(shù)之間素數(shù)的個數(shù)對于[a,b)內(nèi)的合數(shù)而言,它們的因子應(yīng)該在2到sqrt(b)之間,那么我們只要把2到sqrt(n)的倍數(shù)在給定區(qū)間[a,b)的數(shù)篩掉就可以了,為了節(jié)省我們的存儲空間,我們可以將[a,b),左移到[0,b-a)就可以了。
#include<iostream> #include<cstring> using namespace std;typedef long long int ll; const int N = 1000000; bool is_prime_small[N+1],is_prime[N+1]; ll a,b;int main(){while (cin>>a>>b){memset(is_prime,true,sizeof(is_prime));memset(is_prime_small,true,sizeof(is_prime_small));is_prime_small[0]=false;is_prime_small[1]=false;if (a==0){is_prime[0]=false;is_prime[1]=false;}else if (a==1){is_prime[0]=false;}for (ll i=2;i*i<b;i++){if (is_prime_small[i]){for (ll j=i*i;j<b;j+=i){if (j>=a) is_prime[j-a]=false;//在對應(yīng)區(qū)間的數(shù)就不是素數(shù)了}for (ll j=i*i;j*j<b;j+=i) is_prime_small[j]=false;//將[2,sqrt(b))內(nèi)的素數(shù)篩出來}}int cnt=0;for (ll i=0;i<b-a;i++){if (is_prime[i]){cnt++;cout<<i+a<<" ";}}cout<<"cnt="<<cnt<<endl;}return 0; }除此之外還有其他素數(shù)有關(guān)的算法,不過程序設(shè)計競賽主要就是涉及這三種。
最后給一個第八屆藍橋杯b組的試題:
2,3,5,7,11,13,....是素數(shù)序列。 類似:7,37,67,97,127,157 這樣完全由素數(shù)組成的等差數(shù)列,叫等差素數(shù)數(shù)列。 上邊的數(shù)列公差為30,長度為6。2004年,格林與華人陶哲軒合作證明了:存在任意長度的素數(shù)等差數(shù)列。 這是數(shù)論領(lǐng)域一項驚人的成果!有這一理論為基礎(chǔ),請你借助手中的計算機,滿懷信心地搜索:長度為10的等差素數(shù)列,其公差最小值是多少?注意:需要提交的是一個整數(shù),不要填寫任何多余的內(nèi)容和說明文字。如果我沒記錯的話,當(dāng)時比賽的時候好像是錯的。。。
首先我們需要把1000000以內(nèi)的所有素數(shù)篩選出來,這樣可以簡化我們后邊的計算,然后我們對d以及首項a1進行遍歷,然后依次判斷即可。
剛開始的時候我還在糾結(jié)一個問題,也就是說如果當(dāng)前的cnt正好等于M=10,那么是否存在a1-d正好也是素數(shù),那么這里是不是就多了一個了,變成M+1個了,后來我發(fā)現(xiàn),不存在的,在我這里,以a1-d為首項的等差數(shù)列的d’一定小于d。
雖然運行的時候停頓了一下,但是最后還是得到了結(jié)果210。
總結(jié)
以上是生活随笔為你收集整理的判断素数或者求出素数的基本算法 《挑战程序设计竞赛》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++ 字符串
- 下一篇: 64位汇编中的布尔指令