日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

判断素数或者求出素数的基本算法 《挑战程序设计竞赛》

發(fā)布時間:2025/3/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 判断素数或者求出素数的基本算法 《挑战程序设计竞赛》 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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ù)了。

#include<iostream> #include<cstring> using namespace std;const int N = 100; bool is_prime[N+1]; int prime[N+1];int main(){memset(is_prime,true,sizeof(is_prime));is_prime[0]=false;is_prime[1]=false;int cnt=0;for (int i=2;i<=N;i++){if (is_prime[i]){prime[cnt++]=i;for (int j=i*i;j<=N;j+=i){is_prime[j]=false;}}}for (int i=0;i<cnt;i++){cout<<prime[i]<<" ";}cout<<"cnt="<<cnt<<endl;// for (int i=2;i*i<=N;i++){// if (is_prime[i]){// for (int j=i*i;j<=N;j+=i){// is_prime[j]=false;// }// }// }// int cnt=0;// for (int i=0;i<=N;i++){// if (is_prime[i]) prime[cnt++]=i;// }// for (int i=0;i<cnt;i++){// cout<<prime[i]<<" ";// }// cout<<"cnt="<<cnt<<endl;return 0; }

這里的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,長度為62004年,格林與華人陶哲軒合作證明了:存在任意長度的素數(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。

#include<iostream> #include<cstring> using namespace std;const int N = 1000000, M = 10; bool is_prime[N+1];int main(){memset(is_prime,true,sizeof(is_prime));for (int i=2;i*i<=N;i++){if (is_prime[i]){for (int j=i*i;j<=N;j+=i){is_prime[j]=false;}}}int i,cnt;bool flag=false;for (i=2;;i++){for (int j=2;j<=N;j++){if (!is_prime[j]) continue;cnt=1;for (int k=j+i;k<=N;k+=i){if (!is_prime[k]||cnt>M) break;if (is_prime[k]){cnt++;}}if (cnt==M){flag=true;break;}}if (flag) break;}cout<<i<<endl;return 0; }

雖然運行的時候停頓了一下,但是最后還是得到了結(jié)果210。

總結(jié)

以上是生活随笔為你收集整理的判断素数或者求出素数的基本算法 《挑战程序设计竞赛》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。