本章介紹關於素數的一些數論,限於篇幅不給出證實,須要證實的朋友自行相關證實。優化
什麼是素數?只能被本身和1整除的數就是素數。spa
利用這個性質咱們很容易獲得下面的素數判斷方法。code
bool isPrime(int x){ if(x==1)return 0; for(int i=2;i*i<=x;i++) if(x%i==0)return 0; return 1; }
這裏解釋一下爲何是i*i<=x,i*i<x轉化一下就是i<=sqrt(x)。blog
想想,若是咱們枚舉到sqrt(x)都沒有找到能夠被它整除的數,後面也就不可能有能夠被它整除的數了,由於一個>sqrt(x)的數要是被x整除了,它的商確定是<sqrt(x)的,而咱們已經枚舉過<=sqrt(x)的數了,裏面沒有,因此>sqrt(x)的約數也是不可能有的。ci
這種判斷方法的時間複雜度是O(sqrt(n))的,空間複雜度是O(1)的。it
再給出一個判斷方法,這個方法的時間複雜度大概是O(sqrt(n)/3)的,空間複雜度也是O(1)。io
bool isPrime(int x){ if(x==1)return false; if(x==2||x==3)return true; if(x%6!=1&&x%6!=5)return false; for(int i=5;i*i<=x;i+=6) if(x%i==0||x%(i+2)==0)return false; return true; }
證實被我吃了。class
而後就是幾種素數的篩法了。咱們規定下文中討論的[]爲向下取整。效率
首先是著名的埃篩,Eratosthenes篩法。百度
埃篩基於這樣一個想法:對於一個數x,它的倍數2x,3x,4x,5x...都不是質數。
因而,咱們從2開始從小到大掃描每一個數x,把它的倍數2x,3x,4x,...,[N/x]*x標記爲合數。
當掃描到一個數時,若它未被標記爲合數,則它就不能被2~x-1中的任何數整除,它就是質數。
可是咱們會發現,埃篩會重複標記一個數。好比8,它會被2標記,還會被4標記,這樣影響了效率。
因而咱們考慮優化,對於每一個數,從x^2開始把x^2,(x+1)*x,...,[N/x]*x標記爲合數。
給出代碼:
int comp[maxn],prime[maxn]; //合數標記(composite),素數標記 void Eratothenes(int n){//篩到哪裏
for(int i=2;i<=n;i++){ if(comp[i])continue; prime[i]=1;//i是質數 for(int j=i;j<=n/i;j++)comp[i*j]=1; } }
優化後的埃篩的時間複雜度是O(nloglogn),接近線性,並且很好寫,推薦熟記。
那有沒有線性篩呢,有,可是我的認爲,會埃篩就夠了,不必爲了卡常寫到線性。
想了解的能夠自行百度。
接下來給出一些定理,仍是同樣,不證。
1. 惟一分解定理
若整數x>=2,則x必定能夠以惟一的形式表示成若干個素數的乘積。
能夠寫做:x=p1^c1*p2^c2*p3^c3*...*pm^cm。
其中,ci均爲正整數且pi均爲素數,知足p1<p2<...<pm
2. 威爾遜定理
沒啥用的定理,若p爲素數,則(p-1)! ≡ 1(mod p)。
3. 威爾遜定理的逆定理
若對於某一正整數p,有(p-1)! ≡ -1(mod p),則p爲素數。
3. 費馬定理
若p爲素數,x爲正整數,且x和p互質,則x^(p-1) ≡ 1(mod p)。
4. 費馬小定理
若p爲素數,則x^p ≡ x(mod p)。
還有一些東西:( ﹁ ﹁ ) ~→待填坑