数论--素数
一、素?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)常用的方法)
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ù)偶”部分<<便于理解以下代碼
這個(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)
時(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ù)的目的。
精華部分(也算是對(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é)
- 上一篇: 程序员,在北上广深杭赚够100万,就逃回
- 下一篇: 如何有效的使用搜索词