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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

数论--素数

發(fā)布時(shí)間:2024/3/12 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数论--素数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、素?cái)?shù)的概念

素?cái)?shù)又稱(chēng)質(zhì)數(shù)。一個(gè)大于1的自然數(shù),除了1和它自身外,不能被其他自然數(shù)整除的數(shù)叫做質(zhì)數(shù);否則稱(chēng)為合數(shù)。
(素?cái)?shù)是數(shù)論中很重要的部分,所以對(duì)于一些素?cái)?shù)的操作,需要十分的熟練)

二、判斷素?cái)?shù)的方法

1.最基礎(chǔ)的方法(初學(xué)者經(jīng)常用的方法)

bool isprime(int n) {for(int i=2; i<n; i++)if(n%i==0)return false;return true; } //直接從2遍歷到 n,如果之間可以被 n整除,則 n為合數(shù),反之為素?cái)?shù)

2.試除法(相當(dāng)于上個(gè)方法的優(yōu)化)

bool isprime(int n) {for(int i=2; i<=sqrt(n); i++)//寫(xiě)成 i*i<=n可以稍微快一點(diǎn),if(n%i==0) //因?yàn)槊看窝h(huán)都會(huì)計(jì)算sqrt一次,也可以用變量存起來(lái)return false;return true; } /* 如果是合數(shù)的話,那么他的因數(shù)一定會(huì)有分布在sqrt(n)的范圍內(nèi)的, 就是說(shuō)一個(gè)大于sqrt(n)的數(shù)要是可以被 n整除了,它的商肯定是要小于sqrt(n)的, 這時(shí)我們就不需要遍歷 n個(gè)數(shù)字,而直接遍歷sqrt(n)個(gè)數(shù)字就可以了 */

上述兩種方法完全運(yùn)用了素?cái)?shù)的概念,好理解,但是效率不高。
優(yōu)化后的第二種方法也是初學(xué)者經(jīng)常用的,雖然比第一種方法時(shí)間復(fù)雜度小不少,但是也是有O(n1/2),對(duì)于一般的題目只能判斷到1012,所以對(duì)一些再大的數(shù)就很不友好

3.六素?cái)?shù)法(這是在翻博客的時(shí)候發(fā)現(xiàn)的一種方法,在百度百科上也有提到,先放到這里)
建議看一下>>百度百科的“六素?cái)?shù)偶”部分<<便于理解以下代碼

bool isprime(int n) {if(n==1)return false;if(n==2||n==3)return true;//1,2,3的情況特殊判斷if(n%6!=1&&n%6!=5)return false;int k=sqrt(n)+1;for(int i=5; i<k; i+=6)//這一部分和試除法類(lèi)似if(n%i==0||n%(i+2)==0)return false;return true; }

這個(gè)的時(shí)間復(fù)雜度應(yīng)該是 O(n1/2/3),相比上兩種方法,效率還是提高了一些。
三、區(qū)間上的素?cái)?shù)數(shù)量

一般來(lái)說(shuō),一個(gè)和素?cái)?shù)相關(guān)的問(wèn)題都是求[2,n]內(nèi)的素?cái)?shù)。如果用上邊的方法一個(gè)一個(gè)來(lái)判斷,時(shí)間復(fù)雜度為O(n*n1/2),如果n比較大,可能計(jì)算機(jī)要跑幾分鐘。所以這種方法難免會(huì)超時(shí),下面說(shuō)一下可以解決一個(gè)區(qū)間上素?cái)?shù)問(wèn)題的算法。
1.埃式篩法(埃拉托斯特尼篩法)
基本思想:素?cái)?shù)的倍數(shù)一定不是素?cái)?shù)

(動(dòng)圖出處: https://www.cnblogs.com/findwg/p/4901219.html)

const int maxx=1e7;//定義空間大小,1e7大約10MB int prime[maxx+1];//存放素?cái)?shù) bool visit[maxx+1];//true表示被篩掉,表示素?cái)?shù) int E_sieve(int n)//埃式篩,計(jì)算[2,n]內(nèi)的素?cái)?shù) {for(int i=0; i<=n; i++)visit[i]=false;for(int i=2; i*i<=n; i++)//核心代碼if(!visit[i])for(int j=i*i; j<=n; j+=i)visit[j]=true;//標(biāo)記成非素?cái)?shù)int k=0;//作為統(tǒng)計(jì)個(gè)數(shù)的變量for(int i=2; i<=n; i++)if(!visit[i])prime[k++]=i;//儲(chǔ)存素?cái)?shù)return k; }

時(shí)間復(fù)雜度:可以看出來(lái),在核心代碼的那部分,一共要進(jìn)行的循環(huán)次數(shù)為O(n/2+n/2+n/5+…),即O(nloglog2n),有時(shí)候也近似看成O(n)
可以看出,埃式篩法還不錯(cuò),但是也做了一些無(wú)用功,某個(gè)數(shù)字會(huì)被篩選多次,比如12這個(gè)數(shù)字,在2和3的時(shí)候就篩選了兩次。
既然有可優(yōu)化的地方,那必然有更好的算法
2.歐拉篩法(歐拉線性篩)
原理:由于所有合數(shù)都有一個(gè)最小質(zhì)因子,所以在埃氏篩法的基礎(chǔ)上,讓每個(gè)合數(shù)只被它的最小質(zhì)因子篩選一次,以達(dá)到不重復(fù)的目的。

int Oula_gprime() {int get=0;memset(v,0,sizeof(v));v[0]=v[1]=1;for(int i=2; i<=maxx; i++){//cout<<"# i = "<<i<<endl;if (!v[i])prime[get++]=i;for (int j=0; j<get&&i*prime[j]<=maxx; j++){//cout<<"j = "<<j<<"\t"<<"prime[j] = "<<prime[j]<<"\t";//cout<<"i * prime[j] = "<<i*prime[j]<<endl;v[i*prime[j]]=1;if (i%prime[j]==0)break; }//cout<<endl;}return get; }

精華部分(也算是對(duì)埃式篩法的優(yōu)化部分):

for (int j=0; j<get&&i*prime[j]<=maxx; j++) {v[i*prime[j]]=1;if (i%prime[j]==0)break; } /* 我們知道任何合數(shù)都能表示成多個(gè)素?cái)?shù)的積。 所以,任何的合數(shù)肯定有一個(gè)最小質(zhì)因子。 我們通過(guò)這個(gè)最小質(zhì)因子就可以判斷什么時(shí)候不用繼續(xù)篩下去了。 當(dāng) i是 prime[j]的整數(shù)倍時(shí),i*prime[j+1]肯定再次被篩,就跳出循環(huán)。 就比如 i=6,prime[j]=2(這時(shí)候 prime已經(jīng)有了2,3,5), i%prime[j]==0,所以就可以跳出循環(huán)。 因?yàn)樵谙旅?prime[j]=3的時(shí)候,i*prime[j]=18, 在下一次 i=18的時(shí)候,會(huì)再循環(huán)一次,prime[j]=5的時(shí)候也一樣 */

可以發(fā)現(xiàn),在下圖的 i:2~8項(xiàng)中,i * prime[j]的值一直沒(méi)有重復(fù)
打表也可以發(fā)現(xiàn),所有的 i * prime[j]一直都不會(huì)重復(fù)出現(xiàn)
這也就驗(yàn)證了我們一開(kāi)始的對(duì)歐拉篩的另一種叫法:歐拉線性篩,
歐拉篩的時(shí)間復(fù)雜度也就的確可以做到O(n)的大小。

四、結(jié)語(yǔ)
無(wú)結(jié)語(yǔ)

總結(jié)

以上是生活随笔為你收集整理的数论--素数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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