數論基礎原理總結

UPD:2018.4.25 更新了快速求原根的囉嗦的證實html

1、整除的性質算法

1,若是a|b,且b|c,則a|c數組

2,a|b且b|c,那麼a|cdom

3,設m!=0,那麼a|b等價於(m*a)|(m*b)函數

4,設整數x和y知足下式,a*x+b*y=1,且a|n,b|n,那麼(a*b)|n測試

根據性質3可得,(a*b)|(n*b),(a*b)|(n*a),spa

根據性質4可得,(a*b)|x*(n*a)+y*(n*b).net

化簡上式,(a*b)|n*(a*x+b*y)=>(a*b)|n*(1),證畢code

5,若b=q*d+c,那麼d|b的充要條件是d|cxml

其餘

約定0能夠被任何數整除

若2能整除a的最末位,則2|a

若4能整除a的後兩位,則4|a

若8能整除a的後三位,則8|a.以此類推再也不贅述

若3能整除a的各位數字之和,則3|a

若9能整除a的各位數字之和,則9|a

若11能整除a的偶數位數字之和與奇數位數字之和的差,則11|a

同時能被7,11,13整除的數的特徵是,這個數的末三位與末三位之前的數字所組成的數能被7,11,13整除,則這個數就能被7,11,13整除

顯然成立容易忽略的細節?

若a|b,則a是b的一個因子,

若a|b,則a<=b

 

2、GCD

GCD據個人理解能夠形象化的理解爲,數字的最長公共子結構

因此不只僅是兩個數之間的

一堆數的GCD,顯然能夠先從某兩個數的GCD開始,由於答案一定比這個還要小

一堆定序數的GCD有一個性質那就是非嚴格單調遞減,某一段的GCD可能不變,可是其終歸是遞減

這裏有一個偏哲學的解釋,人越多則人們的共性就越少,共性越少則最大共性也越少

 GCD正確性的證實須要知道幾點

若a|b則a<=b

另一個是顯然但容易忽略的事實,a<=b,b<=a,顯然當且僅當a=b時成立

對於a=q*d+r,q|a當且僅當q|r

正確性的證實:

展轉相除法的正確性能夠分紅兩步來證實。

在第一步,咱們會證實算法的最終結果rN−1同時整除ab。由於它是一個公約數,因此必然小於或者等於最大公約數g

在第二步,咱們證實g能整除rN−1。因此g必定小於或等於rN−1。兩個不等式只在rN−1 = g是同時成立。具體證實以下: 

  1. 證實rN−1同時整除ab
    由於餘數rN是0,rN−1可以整除rN−2
    rN−2 = qN rN−1
    由於rN−1可以整除rN−2,因此也可以整除rN−3
    rN−3 = qN−1 rN−2 + rN−1
    同理可證rN−1能夠整除全部以前步驟的餘數,包括ab,即rN−1ab的公約數,rN−1 ≤ g
  2. 證實最大公約數g能整除rN-1
    根據定義,ab能夠寫成g的倍數:a = mgb = ng,其中mn是天然數。由於r0 = a − q0b = mg − q0ng = (m − q0n)g,因此g整除r0。同理可證g整除每一個餘數r1r2, ..., rN-1。由於最大公約數g整除rN−1,於是g ≤ rN−1

由於第一步的證實告訴咱們rN−1 ≤ g,因此g = rN−1。即:

g = GCD(ab) = GCD(br0) = GCD(r0r1) = … = GCD(rN−2rN−1) = rN−1
GCD還有一個性質那就是 a*b=GCD(a,b)*LCM(a,b)
LCM的意思就是最小公倍數
GCD還有一個顯然但容易忽略的事實,GCD(a,b)=GCD(b,a)
可是對於咱們後面講的EXGCD來說,EXGCD(a,b,x,y)=EXGCD(b,a,x,y)雖然其結果一致
可是x,y的值卻交換了,由於x與第一個參數對應,而y則與第二個參數對應
若是y<x,則GCD(x,y)<x,若是咱們設了x爲最小正整數則得出一個矛盾
最小正整數有一個顯然的性質,它>0而且所處集合應當是良序的
顯然>0意味着不等於0
一個顯然可是容易忽略的事實是a*(-b)+(-b)*a=0
也能夠寫成a*(x0-b)-b*(y0+a)=a*x0+b*y0
在瞭解EXGCD以前咱們須要先了解一個基本的事實

整數中的裴蜀定理

對於任意兩個整數,a,b,設d是他們的最大公約數

\displaystyle ax+by=m

有整數解(x,y當且僅當m 是d 的倍數

裴蜀等式有解時必然有無窮多個解。

一般談到最大公約數時,咱們都會提到這個很是基本的事實:給予二整數a、b,必存在有整數x、y使得ax + by = gcd(a,b)

  理解要點

 

  由於r也是A中的元素,且r>=0&&r<d0,若是r>0則說明存在比d0還小的「正」元素,這與假設矛盾

  所以r只能取<=0的整數,r能夠取0

  理解要點2

首先咱們知道ax0+by0=d0

並且咱們知道d0能整除a,b

那麼a*(x0+kb/d0)+b*(y0-ka/d0)=d0

而後咱們顯然能夠獲得

a*(m0x0+m0kb/d0)+b*(m0y0-m0ka/d0)=m0d0

後面我好像不太會了,可是咱們知道m0x0+kb,m0y0-ka因爲k是整數,因此比起上面那個形式

會漏解。。可是因爲整數集是無窮數級,因此即便漏解它仍然有無窮多解(它真的會漏解嗎,至少如今我看來會的)

(更新補充:

 可是咱們會看到上面的證實中,標準的通解(也許叫這個名字吧)形式是,m0x0+kb/d,m0y0-ka/d

 這裏我又發現了一個坑。。那就是我寫的是d0,可是他這裏是d,個人d0就是A集合中最小的正整數,也就是gcd(a,b)

可是他這裏是d...

 奧我發現。。他上面說了。。這個d的意思就是a,b的任意正公約數,那麼d就能整除a和b了

而且d0是最大公約數,那麼d<=d0,那麼b/d>=b/d0,那麼對於同一個整數k,kb/d>=kb/d0

======================================================

可是這裏我真正想說的是,因爲(d表示任意公約數)kb/d,ka/d,最後互相乘以一個係數被約掉。。因此咱們並不關心這個係數是多少

這裏t*b/d0必定能轉化到k*b/d爲何呢,

由於,,d=z*d0..,t*b/d0和k*b/z*d0,咱們一定有辦法將1/z消去,而後規約到t的狀況裏。。因此我認爲(t爲任意整數)t*b/d0就能表明全部解
奧這下我又知道了。。由於任意正約數d的狀況是包含d0的啊!MDZZ

那麼其實咱們經過這個基本事實的證實獲得了合理的解釋

2、EXGCD

EXGCD實際上是基於對以上事實的觀察以及對GCD迭代求解過程的觀察

其實咱們知道GCD基於一個事實,假設第一個參數小於第二個參數GCD(a,b)=GCD(a,b-a)

(此處不妨設a<b,若是a>b那麼GCD(b%a,a)=GCD(b,a)則僅僅至關於交換了a,b的位置)

可是咱們知道一般咱們寫的GCD第一個參數老是大於第二個參數,這也是不一樣於日常的另一種寫法

這裏有一個顯然的事實a%b<b

咱們知道GCD的每一步迭代都對應着一個帶餘除法式子

由於咱們要知道餘數是多少,由於咱們知道一旦求出了餘數咱們爲了保證參數順序就要交換

繼續用大數減去小數,因此GCD的全部迭代的過程都對應着帶餘除法式子,

這就是咱們要寫一堆求餘數式子的緣由,這樣才能找到最大公約數和最初的參數有什麼關係

數學推導能夠有兩種一種是從前日後,另一種是從後往前,首先咱們要寫出來最基本的一堆求餘數式子

(b<a)

a=q1*b+r1(r1<b)

b=q2*r1+r2(r2<r1)

r1=q3*r2+r3(r3<r2)

r2=q4*r3+r4(r4<r3)

r3=q5*r4+r5(設r5=0,r5<r4)

r4=q6*r5+r6(由於r5=0,因此r6=r4)這裏返回GCD的答案r4,算法終止

那麼都說那這些式子迴帶就能夠得解

怎麼迴帶呢,其中一種錯誤的迴帶是a-q1*b=r1

把r1迴帶,咱們看看有沒有辦法算出r1和最大公約數g的關係反解g,此處的g就是r4

(Tip:化簡式子時要觀察式子的結構,一個簡單的想法是觀察目標式子中的元素而後將多餘的元素反解成目標式子中的元素)

r2=q4*(q5*r4)+r4=(1+q4*q5)*r4

r1=q3*(1+q4*q5)*r4+(q5*r4)=(q3+q3*q4*q5+q5)*r4

a-q1*b=(q3+q3*q4*q5+q5)*r4

此時咱們令a=p1*r4,b=p2*r4,由於咱們早已知道r4|a,b

p1*r4-q1*p2*r4=(q3+q3*q4*q5+q5)*r4

設存在x,y使得,x*p1*r4+y*p2*r4=r4

則r4*(x*p1+y*p2-1)=0

而式也能化解爲,r4(p1*r4-q1*p2*r4-q3-q3*q4*q5-q5)=0

證實到這裏咱們必需要找到(q3+q3*q4*q5+q5+1)分解成a和b的份量

因爲都是商數因此,這令我感到證實困難,這種證實的主要困難是選擇了a的係數固定爲一,須要找到a的其餘分解

這個先放在這裏。。閒的時候能夠強行剛一波

(b<a)gcd(a,b)

a=q1*b+r1(r1<b) gcd(b,r1)

b=q2*r1+r2(r2<r1) gcd(r1,r2)

r1=q3*r2+r3(r3<r2)gcd(r2,r3)

r2=q4*r3+r4(r4<r3)gcd(r3,r4)==>

r3=q5*r4+r5(設r5=0,r5<r4)gcd(r4,r5) r5==0 return r4  ==>1*r4+0*r5=gcd(r4,r5)=r4

r4=q6*r5+r6(由於r5=0,因此r6=r4)這裏返回GCD的答案r4,算法終止

對於這堆式子。。咱們能夠將r4的係數固定爲1,而後從下往上迭代

首先咱們將餘數所有挪到左邊

r1=a-q1*b

r2=b-q1*r1

r3=r1-q3*r2

r4=r2-q4*r3

r5=r3-q5*r4

r6=r4-q6*r5

由於咱們總能迭代到r1,因此r4總能表示成(a-q1*b)的線性組合,也就是a,b的線性組合

下面開始實際證實

r4=r2-q4*(r1-q3*r2)=(1+q4*q3)r2-q4*r1(帶入r3)

r4=(1+q4*q3)*(b-q1*r1)-q4*r1=(1+q4*q3)*b-r1(q1+q1*q4*q3+q4)(帶入r2)

r4=(1+q4*q3)*b-(a-q1*b)(q1+q1*q4*q3+q4)(帶入r1)

r4=(1+q4*q3-q1*q1-q1*q1*q4*q3-q4*q1)b-a*(q1+q1*q4*q3+q4)

r4=p1*b-p2*a=xa+yb

而後咱們也能夠先把r2帶入r1,依次,最後r4裏面把r2和r3帶入

這個證實的核心就是發現了一個事實,比r1小的餘數都能表示成r1的線性組合,而比r1小的餘數裏面

一定有一個餘數是最大公約數,最大公約數也可表示成r1的線性組合,而r1又是a,b的線性組合,因此最大公約數也是a,b的線性組合

而且咱們知道一旦知道了每一步的商和餘數咱們就能算出最終最大公約數中a,b的某一個線性組合

可是咱們的程序應該怎麼寫呢。。

因爲這是一個遞歸的過程,若是咱們要採用回溯迭代而不是遞歸生成目標多項式也就是從上往下一步帶入

因此咱們要知道前一步和後一步存在什麼關係,首先咱們求的是一個a,b的係數,那麼咱們經過上述步驟迴帶,

咱們知道GCD(a,b)=GCD(b,a%b),因而咱們根據上面講的性質之一就能夠發現

存在事實,ax1+by1=bx2+(a%b)y2

在下取整乘法裏咱們能夠寫成,ax1+by1=bx2+(a-b*a/b)y2

要想獲得x1,x2,y1,y2的關係一個簡單的想法,兩邊都整理成a*p1+b*q1=a*p2+b*q2

因此這裏有一個顯然可是容易忽略的事實,a*p1+b*q1=a*p2+b*q2

的一組解一定有,p1=p2,q1=q2

可是別忘了,p1!=p2,q1!=q2的狀況,此時設k1,k2爲整數集合中的數

則p2=p1+k1,q2=q1+k2,則a*p1+b*q1=a*(p1+k1)+b*(q1+k2)

整理可得ak1+bk2=0,咱們能夠得出k1=b/d0,k2=-a/d0,若是d0|a,b

能夠知道d0必定存在,由於能夠取0,1等等值

根據其中一組解的思路,兩邊整理成一樣形式的

ax1+by1=ay2+b(x2-a/b*y2)

則x1=y2,y1=(x2-a/b*y2),因此其實咱們按照這個式子迴帶答案就行,由於咱們知道遞歸的最後一步必定有解

代碼實現有一點,當前x的值是x2,y的值是y2,仍然用x存x1則x=y=y2;可是y=x-a/b*y就會變成y2-a/b*y2

由於x2被覆蓋,因此呢,這裏須要臨時變量保存x2的值

 

而後令我困惑的是不斷迭代的這個過程其實沒有用到上面推導的結論咱們只是

一味的迭代。。

當咱們想要真正模擬迭代求解的過程時

在此以前還須要強調以前的性質那就是函數定義的參數順序,定義gcd(a,b,x,y)能夠順便求出x*a+y*b=gcd(a,b)中x,y的一組特解

因此咱們知道x對應於a,y對應於b,x,y並不知足交換的性質

這裏參考上面的式子就行,假設的話,截斷式子就能夠

譬如設d是最大公約數,d=r3=r1-q3*r2,此時A=r1,B=r2,x1=1,y1=-q3

而後咱們將r2帶入,d=r1-q3*(b-q2r1)=(-q3)*b+(1+q2q3)r1,此時A=b,B=r1,x2=-q3=y1,y2=x1-y1*b/r1(實際上b/r1就是q2)

而後其實從這裏咱們就足以發現事實(其實不嚴謹,可是日後推導顯然能夠規約到這兩步上面)。。那就是x2=y1,y2=x1-y1*b/r1,也就是說其實這個過程本質和上面的事實仍是同樣的

因此咱們就沒必要顧慮這個過程和上面的事實沒有聯繫。。他們只是從不一樣角度觀察而已

因此反向帶入和咱們反解係數gcd(a,b)=gcd(b,a%b)實際上是同樣的啦!

 用exgcd求逆元怎麼求呢,求k*M=1(mod N)M<N,那麼其實這個問題至關於k*M+p*N=1,而咱們知道M,N互質則有,k*M+p*N=gcd(M,N)一定有解

因此利用exgcd便可求出知足等式的一個k,(其實exgcd還知足一個性質,那就是求出來的|k|+|p|是最小的,這個用概括法容易正,由於每一步都是最小的

可是k可能會小於零,好比7,8會求得,7*-1+8=1,等式裏沒什麼問題,可是咱們求的是逆元,那個式子還能夠寫成,(7*-1)%8=1,也就是說只要在等式裏找到了

一個k,那麼這個k一定對應一個0~N-1大小的逆元,由於和(7*-1+p*8)%8=1是等價的,p是多大並不重要,模意義下跟沒有同樣,

其實和,(7*(p*8-1))%8=1同樣,展開可得,-7+7*p*8=1(mod 8),那麼咱們可讓p=7p嘛。。那麼就變成了上面的(7*-1+p*8)%8=1,這樣就等價了

因此因爲乘法逆元的意義,他就是一個0~N-1的數,假如k<0,則咱們須要求p*8+k>0最小的數,那麼咱們能夠先k%8,將大於8的部分的負數都搞掉

而後k是一個在0~N-1下的負數,此時咱們再給他加上N就獲得答案,可是對於正數,雖然加上N沒影響,可是會大於N,因此咱們最後在模一個N

那麼這個逆元就會被表示成(k%n+n)%n,正負數通用

那麼還有一個理解是,何時返回答案呢,那就是,右邊的大的數,被左邊%成了0,那麼這不就說明左邊纔是最終的答案嘛,返回左邊

也就是if(b==0) return a;這裏約定右邊比左邊大

爲何普通線性同餘方程x解的最小距離爲b/gcd

每每咱們須要求解的方程並非a*x+b*y=gcd(a,b)而是更常規的a*x+b*y=n

而後能夠經過對a*x+b*y=gcd(a,b)方程的求解,轉化成爲求二元一次不定方程a*x+b*y=n

若gcd(a,b)不能整除n,這個方程無整數解,反之,若解得a*x+b*y=gcd(a,b)的解爲x0,y0,

則方程兩邊同乘n再除以gcd(a,b)得a*(n/gcd(a,b)*x0)+b*(n/gcd(a,b)*y0)=n

因此方程解爲x=n/gcd(a,b)*x0,y=n/gcd(a,b)*y0。

 

更一般的是:咱們須要求解方程的最小整數解

若咱們已經求得x0,y0爲方程中x的一組特解,那麼

x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t(t爲任意整數)也爲方程的解

且b/gcd(a,b),a/gcd(a,b)分別爲x,y的解的最小間距,因此x在0~b/gcd(a,b)區間有且僅有一個解,

同理y在0~a/gcd(a,b)一樣有且僅有一個解,這個解即爲咱們所需求的最小正整數解。

 

爲何b/gcd(a,b),a/gcd(a,b)分別爲x,y的解的最小間距?

解:假設c爲x的解的最小間距,此時d爲y的解的間距,因此x=x0+c*t,y=y0-d*t(x0,y0爲一組特解,t爲任意整數)

      帶入方程得:a*x0+a*c*t+b*y0-b*d*t=n,由於a*x0+b*y0=n,因此a*c*t-b*d*t=0,t不等於0時,a*c=b*d

      由於a,b,c,d都爲正整數,因此用最小的c,d,使得等式成立,ac,bd就應該等於a,b的最小公倍數a*b/gcd(a,b),

      因此c=b/gcd(a,b),d就等於a/gcd(a,b)。

 

因此,若最後所求解要求x爲最小整數,那麼x=(x0%(b/gcd(a,b))+b/gcd(a,b))%(b/gcd(a,b))即爲x的最小整數解。

x0%(b/gcd(a,b))使解落到區間-b/gcd(a,b)~b/gcd(a,b),再加上b/gcd(a,b)使解在區間0~2*b/gcd(a,b),

再模上b/gcd(a,b),則獲得最小整數解(注意b/gcd(a,b)爲解的最小距離,重要

摘自:http://blog.csdn.net/non_cease/article/details/7364092

3、同餘理論

若a,b爲兩個整數,且它們的差a-b能被某個天然數m所整除,則稱a就模m來講同餘於b,或者說a和b關於模m同餘

記爲a=b(mod m)(同餘符號懶得弄了,暫時就拿等號代替)

它意味着,a-b=m*k(k爲某一個整數),例如32=2(mod5) k=6

還有一種理解同餘的說法,那就是兩個數把多餘的部分(大於模數的部分)砍掉,剩下的數值同樣,那麼咱們就說這兩個數同餘

對於整數a,b,c和天然數m,n, 對模m同餘具備如下一些性質

1,自反性,a=a(mod m)

2,對稱性,若a=b(mod m) 則 b=a(mod m)

3,傳遞性,若a=b(mod m),b=c(mod m),則a=c(mod m)

4,同加性,若a=b(mod m),則a+c=b+c(mod m)

5,同乘性,若a=b(mod m),則a*c=b*c(mod m)

  若a=b(mod m) c=d(mod m) 則 a*c=b*d(mod m)

6,同冪性,若a=b(mod m),則an=bn(mod m)

7,推論1,a*b mod k=(a mod k)*(b mod k) mod k

8,推論2,若a mod p=x, a mod q=x,p、q互質,則a mod p*q=x

證實,p,q互質則必定 存在整數s,t使得 a=sp+x,a=tq+x

那麼顯然咱們能夠獲得,sp=tq,由於p,q互質,因此必定存在s=kq

因此a=(kq)p+x=kqp+x,所以 a=x(mod p*q)

 

可是同餘不知足同除性,即不知足a div n = b div n (mod m)

咱們知道若是div n是逆元的話,設L=inv(n,m),則a*L=b*L(mod m)是知足同乘性質

可是此處卻說不知足,可見並非逆元乘法當除法?

因此這裏是一個有疑惑的地方

 


關於同餘這裏有一個快速的指數取餘的算法

那就是快速冪,快速冪基於兩個事實,咱們能夠在log的時間把一個數分解成2進制

ab=ab0*ab1....*abn,而後咱們知道b0到bn的和就是b,可是咱們沒必要求出具體數值

例如11011=1+10+1000+1000,咱們能在對數時間內求得,a,a*a,a*a*a*a,咱們知道

對於二進制的偶數次冪,咱們能夠直接利用結果,奇數次冪能夠用a*偶數次冪,也就是基於偶數加一等於奇數這一基本事實

因此咱們能夠組裝成任意的冪次,注意特判b=0的狀況

 

求解線性同餘方程

定理1:對於方程a*x+b*y=c,該方程等價於a*x=c(mod b),有整數解的充分必要條件是:c%GCD(a,b)=0

根據定理1,對於方程a*x+b*y=c,咱們能夠先用擴展歐幾里得算法(EXGCD)求出一組x0,y0,

也就是ax0+by0=GCD(a,b),而後兩邊同時除以GCD(a,b),再乘以c

這樣就獲得了,a/GCD(a,b)*c*x0+b/GCD(a,b)*c*y0=c,咱們也就找到了方程的一個解

定理2:若GCD(a,b)=1,且x0,y0爲a*x+b*y=c的一組解,

則該方程的任一解可表示爲,x=x0+b*t,y=y0-at

這裏有一個顯然但容易忽略的事實,GCD(a/GCD(a,b),b/GCD(a,b))=1,即兩個數都除以GCD,則運算後的結果互質

並且咱們也能夠這麼想,ax0+by0=GCD(a,b),同除以GCD(a,b),a/GCD(a,b)*x0+b/GCD(a,b)*y0=1,

咱們知道它的解必定存在,那麼根據上述的某一條性質咱們能夠得出結論,a/GCD(a,b)與b/GCD(a,b)互質

而且咱們知道GCD(a,b),的含義在這裏是可以整除a,b的最大約數,若是約數比GCD(a,b)還大,那麼a,b至少有一方不能被此約數整除

 

因此根據定理2,考慮方程a*x+b*y=c=>a/GCD(a,b)*x+b/GCD(a,b)*y=c/GCD(a,b)

因而咱們能夠獲得方程,A*x+B*y=C,GCD(A,B)=1,因而咱們能夠獲得(x0,y0是ax+by=c的一組解)

x=x0+B*k,y=y0-A*k,(A=a/GCD(a,b),B=b/GCD(a,b)),因此這裏咱們就求得了a*x+b*y=c的全部解

咱們在求出特解x0,y0時,向全部解推廣時,運用了上面一個顯然的事實

a*(-b)-b*(a)=0,那麼咱們知道當你得到了ax0+by0=c,你能夠寫成a(x0+bk)+b(y0-ak)=c

可是這裏k取整數則會漏解,由於咱們知道要想這個式子成立,x0須要加上一個b爲分子,能整除a,b的的數做爲分母

y0須要減去一個a爲分子,能整除a,b的數做爲分母,(這兩個分母固然取同樣的)這樣才能知足等式

可是咱們知道能整除a,b的數很是多,but 咱們知道了能同時整除a,b最大的數,咱們取這個數做分母

k取任意整數就能得到全部解,你擔憂漏掉a,b其餘公共約數做爲分母的狀況的解?不存在的,由於k是任意的

k能枚舉全部其餘公約數爲分母比(例如b/GCD(a,b))大的部分的全部因子的狀況,因此這有點相似於基元的思想

 

因此咱們來推一下這個解最終的形式應該是怎麼樣的,要求ax+by=c的解

咱們只能先求出ax+by=GCD(a,b)的解,設這組解爲x0,y0

給這組解同乘以c/GCD(a,b),這樣咱們就獲得了ax+by的一組解,X0=x0*c/GCD(a,b),Y0=y0*c/GCD(a,b)

而後咱們知道通解X=X0+B*k,Y=Y0-A*k,帶入X0,Y0,A,B,(A=a/GCD(a,b),B=b/GCD(a,b))

X=x0*c/GCD(a,b)+b/GCD(a,b)*k,Y=y0*c/GCD(a,b)-a/GCD(a,b)*k,其中k能夠取任意整數

但在實際問題中,咱們每每被要求去求最小整數解,也就是一個特解,

X=(X%B+B)%B,Y=(Y%A+A)%A,

因此就是X1=(X0%B+B)%B, Y1=(Y0%A+A)%A

那麼爲何這樣就能求出最小整數解呢

由於全部解的形式後面都帶B*k,或者A*k,咱們把這些都%掉

就剩下最小的X0,Y0,而後咱們知道%剩下的這些必定小於B或A(取模運算)

那麼若是此時(c語言%運算)%的結果小於零,可是它的絕對值的結果必定小於B或A

此時咱們再給他加上B或A,因此咱們求出的是最小非負整數解

由於這個解有多是零

 

逆元

若a*x=1(mod b) ,a,b互質,則稱x爲a的逆元,記爲a-1

根據逆元的定義,可轉化爲a*x+b*y=1,咱們知道若是a,b互質,那麼GCD(a,b)=1

那麼咱們只需跑一趟EXGCD就能算出來a的逆元是多少

求逆元還有一個線性算法,具體過程以下

首先1-1=1(mod p) 

而後咱們設p=k*i+r,是p/i的帶餘除法,令i>1&&i<p,令p是質數,那麼全部i都與p互質,都互質那麼就都存在逆元

而後咱們顯然能夠知道r<i,這意味着r也是存在逆元的,再將這個式子放到mod p的意義下

k*i+r=0(mod p)

在兩邊同時乘上i-1,r-1就會獲得

k*r-1+i-1=0(mod p)

i-1=-k*r-1(mod p)

i-1=-(p/i)*(p%i)-1(mod p)

由於咱們不想得出一個小於零的結果,咱們知道

p-(p/i)=p/i(mod p) 因此做替換

i-1=(p-(p/i))*(p%i)-1(mod p)

這就是線性求逆元的遞推式子了

實際上這也提供了一種O(logn)底數爲2,

的時間內求出單個數逆元的方法,只要直接按照那個公式遞歸就能夠了。能夠證實p mod i<i/2

每次遞歸問題規模減半,最終只會有O(logn)次遞歸,GCD貌似只須要位數乘5的複雜度,這個要比GCD快一個常數

我忽然想到了GCD和線性差分方程,然而線性差分方程又和斐波那契數列有關(斐波那契數列是線性差分方程的一種特殊形式)

GCD爲何和線性差分方程有關呢

好比說這種形式

r1=a-q1*b

r2=b-q1*r1

r3=r1-q3*r2

r4=r2-q4*r3

r5=r3-q5*r4

r6=r4-q6*r5

這不就是典型的差分形式麼

整數的惟一分解定理

任意正整數都有且只有一種方式寫出其素因子的乘積表達式

A=(p1^k1)*(p2^k2)*(p3^k3)....*(pn^kn),其中pi爲素數

這裏有一個顯然可是容易忽略的事實

那就是A和A/(pi^ki)互質

 

約數和公式

對於已經分解的整數,A=(p1^k1)*(p2^k2)*(p3^k3)....*(pn^kn)

有A的全部因子之和爲

S=(1+p1^1+p1^2+...+p1^k1)*(1+p2^1+p2^2+...p2^k2)*(1+p3^1+p3^2+...+p3^k3)*...(1+pn^1+pn^2+...pn^kn)

這個很好理解,由於A的全部因數必然是A中全部素因子及其冪次的組合(與順序無關全部和排列沒有關係)

 

同餘模公式

(a+b)%m=(a%m+b%m)%m

(a*b)%m=(a%m+b%m)%m

這個很是好理解,由於若是a=km+r,則你先%m對答案無影響

若是k=0,也是沒有影響的

素因子分解

不斷對A的素因子取模,只要A%pi==0,則cnt[pi]++,A/=pi,當A%pi!=0時咱們分解pi+1

可是咱們須要對A自己就是一個素數進行特判

求A^B的全部約數之和

sum=(1+p1^1+p1^2+...+p1^(k1*B))*(1+p2^1+p2^2+...+p2^(k2*B))*...*(1+pn^1+pn^2+...+pn(kn*B))

對於每個pi咱們須要

遞歸二分求等比數列1+pi+pi^2+...+pi^n

本質就是咱們提出來一個因子使得問題的規模縮小一半

n分奇偶來討論,若是n是奇數則一共有偶數項好比說n=7

下取整除法

pi^0  pi^4

pi^1  pi^5

pi^2  pi^6

pi^3  pi^7

因此咱們就發現了pi^(7/2+1)+...+pi^7=(1+pi^1+...+pi^(7/2))*(pi^(7/2+1))

而後1+pi^1+pi^2+...+pi^7=(1+pi^1+...+pi^(7/2))+(1+pi^1+...+pi^(7/2))*(pi^(7/2+1))=(1+pi^1+...+pi^(7/2))*(1+pi^(7/2+1))

其實咱們發現若是n是奇數。。則都是知足這個規律的

若是n是偶數,好比說n=8

pi^0  pi^5

pi^1  pi^6

pi^2  pi^7

pi^3  pi^8

可是咱們發現少了pi^4,因此偶數狀況的形式應該是(1+pi^1+pi^2+...+pi^(n/2-1))*(1+pi^(n/2+1))+pi^(n/2)

             奇數狀況的形式應該是(1+pi^1+pi^2+...+pi^(n/2))*(1+pi^(n/2+1))

因此這樣咱們就能遞歸求解等比數列和了

 

中國剩餘定理 CRT

 設天然數m1,m2,...,mr兩兩互素,並記N=m1*m2*...*mr,則同餘方程組

x=b1(mod m1)

x=b2(mod m2)

...

x=br(mod mr)

在模N同餘的意義下有惟一解

 僅僅是這個結論,它並不顯然,可是隻要咱們能構造出解,就證實了這個結論

證實:

考慮方程組

(i>=1&&i<=r)

x=0 (mod m1)

...

x=0(mod mi-1)

x=1(mod mi)

x=0(mod mi+1)

...

...

x=0(mod mr)

因爲諸mi兩兩互素,這個方程組做變量替換,令x=(N/mi)*y

方程組等價於解同餘方程,(N/mi)*yi=1(mod mi),咱們知道GCD(N/mi,mi)=1

因此yi必定有解,則xi=(N/mi)yi

則方程組的解爲X=x1*b1+x2*b2+...+xr*br(mod N)

答案超過N怎麼辦。。咱們邊算邊模就好了

 

斐波那契數列,常係數差分方程,待定係數法求通解

 

因此最終答案就是s^n(f1-rf0)+r^n(sf0-f1)/(s-r)

這是這種方程的通解,而後對於項數很大的常係數差分方程,咱們能夠利用矩陣快速冪

[F(n-1),F(n-2)]*(a   1)=[a*F(n-1)+b*F(n-2),F(n-1)]=[F(n),F(n-1)]

        (b   0)

而後依次類推就好了,就能一直算出後面的項

 

卡特蘭數

求卡特蘭數列的第n項,能夠用以下幾個公式

1.遞歸公式1

  

2.遞歸公式2

    

3.組合公式1

    

4.組合公式2

      

素數理論

 素數的斷定

在數據範圍比較小的狀況下,咱們能夠sqrt(N)判斷一個數是否是素數,若是數據規模是S則總共須要S*sqrt(S)才能判別全部數,很是慢

它的原理就是考慮全部<=sqrt(N)的N的約數,爲何不考慮>sqrt(N)的約數?由於若是一個約數大於sqrt(N)那麼另一個約數一定小於sqrt(N)

 

對於數據範圍較大的狀況,咱們須要素數篩法

一個經典的素數篩法是這樣的,

先將2~N(1不是素數不考慮)之間全部數寫在紙上,

在2的上面畫圈,而後劃去2的其餘倍數,第一個既沒有畫圈也沒被劃去的數是3

在3的上面畫圈,而後劃去3的其餘倍數

重複上面這個過程,知道<=N的全部數都被考慮過畫圈仍是被劃去

i是過程當中第一個既沒有畫圈也沒被劃去的數

其中咱們在枚舉i的倍數時,只需從i*i開始篩,由於k*i(k<i)的狀況已經被考慮過

 

從上述算法咱們能夠發現事實

該算法會形成重複篩除合數,

30=2*15=5*6 因此說30會被重複篩除

 

因此這裏有了一個線性的篩法

首先,明確一個條件,任何合數都能表示成一系列素數的乘積

考慮i是不是質數

1.若是i是素數的話,那簡單,一個大的素數i乘以不大於i的素數,這樣篩除的數跟以前的是不會重複的

2.若是i是合數,此時i能夠表示成遞增素數相乘i=p1*p2*p3*...*pn,pi都是素數

(i>=2&&i<=n),pi<=pj(i<=j),p1是最小的係數

這種篩法的關鍵就在於,當咱們判斷p1==prime[j]的時候,再也不進行篩除,開始下一輪

何時判斷p1==prime[j]呢,因爲prime數組單調遞增(從小往大篩除順序決定的)

因此當i第一次碰到,i%prime[j]==0,就說明了p1==prime[j],由於prime[j]是i最小的質因數

能夠直觀地舉個例子,當i=2*3*5,咱們能夠篩去2*i,可是沒有必要篩除3*i

若是i'=3*3*5,因爲i'%2!=0,因此2*i'必定被篩去,可是3*i==2*i',便可以表示成一個更大的合數和一個更小的質數的乘積

 

這個終止條件咱們還能夠這麼看待,i%prime[j]==0

i=k*prime[j]

此時不終止算法咱們將篩,i*prime[j+1],而prime[j+1]>prime[j]

i*prime[j+1]=k*prime[j]*prime[j+1]=(乘法交換律)k*prime[j+1]*prime[j]

咱們看到k*prime[j+1]是比i大的合數,prime[j]是比prime[j+1]小的質數

因此仍然是避免了下一個篩除的數能夠表示成一個更大的合數和更小的質數的乘積

 

並且咱們知道這個算法的核心就在於

每一個數咱們只用他最小的質因子去篩除

 

還有兩個結論能夠證實

1.一個數不會被重複篩除

2.合數確定會被篩除

 爲何一個數不會被重複篩除呢。。仍是基於前面對數字的惟一表示法的限定

我說的這個惟一表示法是什麼呢,就是咱們知道一個數能夠被分解成惟一素因子的冪次的乘積的形式

可是若是這麼多散開的因子(2^3散開就是2*2*2),不按照固定的規則排列,那麼顯然有n!的排列方式(這裏只是粗略地算了一下,實際應該是可重集合排列

因此這樣不行,咱們把它全部素因子所有排序。。那麼他就能夠表示成i*a,i是它最小的素因子,a固然不用管啦,咱們把它內部當作有序的不就行了嗎

固然a的最小素因子是大於等於i的,

因此在篩2*3*5時,爲何不篩素因子3,5呢,篩3的話會篩掉3*2*3*5,然而這和排序後的2*3*3*5是等價的,素數2能夠輕易處理這種狀況

篩5呢,5*2*3*5,然而和排序後的2*3*5*5等價,3*5*5遍歷2時便可處理,當前處理則是不明知的重複勞動

內循環有一個細節,i*pr[j]<maxn,若是沒有這個。。不只會多跑。。並且可能會越界re

 

假設合數不能被篩除,則說明合數不能表示成最小質數i*a(最小質數大於等於i的數),這顯然是不成立的。。可是我感到這是不嚴謹的,,後續再補

素數的相關定理

1.惟一分解定理

2.威爾遜定理

若p爲素數,則(p-1)!=-1(mod p)(!是階乘符號)

威爾遜定理的逆定理也成立

 

3.費馬定理

 若p爲素數,a爲正整數,且,a和p互質,則a^(p-1)=1(mod p)

證實:

首先,p-1個整數,a,2a,3a,...,(p-1)a  中沒有一個是p的倍數(a與p互質)

其次,a,2a,3a,...,(p-1)a中沒有任何兩個同餘於mod p

由於a=1(mod p) a*i=i(mod p) (i>=1&&i<p)(這個是錯的)

由於沒有任何一個數能表示成 ka=qp+r,其中q>=1

q只能等於0,因此每一個(等會這個也是錯的)

假設存在s1,s2(均小於等於p-1)使得,a*s1=a*s2(mod p),且s1!=s2,a與p互質

兩邊同乘以a的逆元能夠獲得

s1=s2(mod p),可是s1,s2都<=p-1&&>=1,s1必定等於s2,這與假設矛盾,所以不存在s1,s2

也就不存在

因而:a,2a,3a,...,(p-1)a,對mod p的同餘既不爲0,也沒有兩個同餘相同,

 因爲s*a!=s(mod p),因此咱們只有算一下才知道是多少

而且mod p的結果有p個0~p-1,可是沒有0,因此就剩下p-1個,然而這p-1個結果還各不相同,

因此說這p-1個數對模p的同餘結果必定是,1,2,3,...,p-1的某種排列

也就是,a*2a*3a*...*(p-1)a=1*2*3*...*(p-1)(mod p)

化簡能夠獲得,a^(p-1)*(p-1)!=(p-1)!(mod p)

因爲(p-1)!和p顯然互質,因此(p-1)!的逆元必定存在

因此咱們兩邊同時乘以(p-1)!的逆元,式子就變成了a^(p-1)=1(mod p)

其實這是一種特殊狀況,通常狀況下,若p爲素數,則a^p=a(mod p)

這就是著名的費馬小定理

 

Miller-Rabin素數測試

 說Miller-Rabin測試之前先說兩個比較高效的求a*b% n 和 ab %n 的函數,這裏都是用到二進制思想,將b拆分紅二進制,而後與a相加(相乘)

下面這個方法還有另一個名字,俄羅斯乘法(霧)

複製代碼
// a * b % n
//例如: b = 1011101那麼a * b mod n = (a * 1000000 mod n + a * 10000 mod n + a * 1000 mod n + a * 100 mod n + a * 1 mod n) mod n

ll mod_mul(ll a, ll b, ll n) {
ll res = 0;
while(b) {
if(b&1) res = (res + a) % n;
a = (a + a) % n;
b >>= 1;
}
return res;
}
複製代碼

 當相乘的兩個數在long long 範圍內的時候咱們可使用O(1)乘法

inline LL Multiply(LL x, LL y)
{
    LL w = x * y - (LL)((double)x * y / p + 0.001) * p;
    if(w < 0) w += p;
    return w;
}
複製代碼
//a^b % n
//同理
ll mod_exp(ll a, ll b, ll n) {
ll res = 1;
while(b) {
if(b&1) res = mod_mul(res, a, n);
a = mod_mul(a, a, n);
b >>= 1;
}
return res;
}
複製代碼

下面開始說Miller-Rabin測試:

  費馬小定理:對於素數p和任意整數a,有ap ≡ a(mod p)(同餘)。反過來,知足ap ≡ a(mod p),p也幾乎必定是素數。

  僞素數:若是n是一個正整數,若是存在和n互素的正整數a知足 an-1 ≡ 1(mod n),咱們說n是基於a的僞素數。若是一個數是僞素數,那麼它幾乎確定是素數。

  Miller-Rabin測試:不斷選取不超過n-1的基b(s次),計算是否每次都有bn-1 ≡ 1(mod n),若每次都成立則n是素數,不然爲合數。 

僞代碼:

複製代碼
Function Miller-Rabin (n : longint) :boolean;
begin
for i := 1 to s do
begin
a := random(n - 2) + 2;
if mod_exp(a, n-1, n) <> 1 then return false;
end;
return true;
end;
複製代碼


注意,MIller-Rabin測試是機率型的,不是肯定型的,不過因爲屢次運行後出錯的機率很是小,因此實際應用仍是可行的。(一次Miller-Rabin測試其成功的機率爲3/4)

 

前邊說的僞代碼實現很簡短,下面還有一個定理,能提升Miller測試的效率:

二次探測定理

  若是p是奇素數,則 x2 ≡ 1(mod p)的解爲 x = 1 || x = p - 1(mod p);

能夠利用二次探測定理在實現Miller-Rabin上添加一些細節,具體實現以下:

複製代碼
bool miller_rabin(ll n) {
if(n == 2 || n == 3 || n == 5 || n == 7 || n == 11) return true;
if(n == 1 || !(n%2) || !(n%3) || !(n%5) || !(n%7) || !(n%11)) return false;

ll x, pre, u;
int i, j, k = 0;
u = n - 1; //要求x^u % n

while(!(u&1)) { //若是u爲偶數則u右移,用k記錄移位數
k++; u >>= 1;
}

srand((ll)time(0));
for(i = 0; i < S; ++i) { //進行S次測試
x = rand()%(n-2) + 2; //在[2, n)中取隨機數
if((x%n) == 0) continue;

x = mod_exp(x, u, n); //先計算(x^u) % n,
pre = x;
for(j = 0; j < k; ++j) { //把移位減掉的量補上,並在這地方加上二次探測
x = mod_mul(x, x, n);
if(x == 1 && pre != 1 && pre != n-1) return false; //二次探測定理,這裏若是x = 1則pre 必須等於 1,或則 n-1不然能夠判斷不是素數
pre = x;
}
if(x != 1) return false; //費馬小定理
}
return true;
}
複製代碼

 

  前邊這個算法通過測試仍是比較靠譜的,能夠用做模板。本菜也找過其餘模板,但是有的竟然把9測成素數,汗 -_-!


額,這個是我轉的

尊重做者:AC_Von 原創,轉載請註明出處:http://www.cnblogs.com/vongang/archive/2012/03/15/2398626.html

 Miller-Rabin理解的時候有一個我本身的小trick

n%(n-2)的範圍是0~n-3,而不是0~n-1,這一點千萬別搞錯!

而後0~n-3,加上2,就變成了2~n-1,make sense

歐拉定理

費馬定理是用來闡述在素數模下,指數的同餘性質。當模式合數的時候,就要應用範圍更廣的歐拉定理

 

歐拉函數:對正整數n,歐拉函數是小於等於n的數中與n互質的數的數目

歐拉函數又稱爲phi函數,例如phi(8)=4,由於1,3,5,7與8互質

引理1:

1.若是n爲某一個素數p,則phi(p)=p-1

2.若是n爲某一個素數p的冪次p^a,則phi(p^a)=(p-1)*p^(a-1)

3.若是n爲任意兩個互質的數a,b的乘積,則phi(a*b)=phi(a)*phi(b)

證實:

1.顯然

2.由於比p^a小的正整數一共有p^(a)-1個

其中,全部能被p整除的數,均可以表示成p*t(t=1,2,3,...,p^(a-1)-1),若是t=p^(a-1)-1+1=p^(a-1)

則pt=p^a,不知足比p^a小的條件,因此t只能到p^(a-1)-1

也就是說一共有p^(a-1)-1個數能被p整除,從而不與p^a互質

因此phi(p^a)=(p^(a)-1)-(p^(a-1)-1)=p^a-p^(a-1)=(p-1)*(p^(a-1))

3.在比a*b小的a*b-1個整數中,只有那些既和a互質(phi(a)個),又和b互質(phi(b) 個)

的數纔會與a*b互質,顯然知足這種條件的數有phi(a)*phi(b)個,因此有phi(a*b)=phi(a)*phi(b)

 

引理2:

設n=p1^a1+p2^a2+p3^a3+...+pk^ak

爲正整數n的素數冪乘積表達式

則phi(n)=n*(1-1/p1)*(1-1/p2)*...*(1-1/pk)

證實:因爲諸素數冪之間是互質的,根據引理1得出:

phi(n)=phi(p1^a1)*phi(p2^a2)*...*phi(pk^ak)

=p1^a1*(1-1/p1)*p2^a2*(1-1/p2)*...*pk^ak*(1-1/pk)

=p1^a1*p2^a2*...*pk^ak*(1-1/p1)*(1-1/p2)*...*(1-1/pk)

好比phi(100)=phi(2^2*5^2)=100*(1-1/2)*(1-1/5)=100*2/5=40

歐拉定理

若a與m互質,則a^(phi(m))=1(mod m)

 

Pollard Rho算法求大數因子

首先,對於任意一個偶數,咱們均可以提取出一個2的質因子,若是結果仍然爲偶數,則可繼續該操做

直至其化爲一個奇數和2的多少次冪的乘積,

那麼咱們能夠假定這個奇數能夠被表示爲N=2*n+1,若是這個數是合數,那麼必定能夠寫成N=c*d的形式

不難發現式子中的c,d都是奇數,不然N是偶數,不妨設c<d,c=d怎麼辦,c=d咱們則能夠寫成c=1,d=N=c*d,這樣就行了

咱們能夠令a=(c+d)/2,b=(c-d)/2

那麼咱們能夠獲得,a*a=c^2+d^2+2cd/4,b*b=c^2+d^2-2cd

a*a-b*b=4cd/4=cd=N

則N=a*a-b*b

這正是Fermat整數分解的基礎

由基本不等式可得 a>=sqrt(c*d)=sqrt(N)

那麼咱們就枚舉大於N的徹底平方數a*a

計算a*a-N的值,判斷計算的結果是不是一個徹底平方數,若是是的話,則a+b和a-b都是N的因子(由於N=a^2-b^2=(a+b)*(a-b)=c*d)

而後咱們就能夠將算法遞歸地進行下去,直到求出n的全部質因子

 

pollard-rho。是一個尋找n的因子的方法。基於這個事實:若是a不爲n的倍數,那麼gcd(a,n)爲n的一個因子。

I、選取一個x1

II、利用函數計算出x2使得x2-x1不被n整除。

III、若是gcd(x2-x1,n)>1那麼找到因子,結束過程

IV、不然重複I。

因此這裏這個顯然可是容易忽略的事實,若是a不爲n的倍數,那麼gcd(a,n)爲n的一個因子。派上大用場了。。

具體操做當中,咱們一般使用函數 x[i+1]=(x[i]*x[i]+c)mod n 來計算逐步迭代計算a和b的值

實踐中一般取c=1,即b=a*a+1,在下一次計算中,將b的值賦給a,

再次使用上式來計算新的b值,當a,b出現循環時,便可退出進行判斷,固然初值由本身肯定,

 

可是這樣的話判斷循環比較麻煩,咱們能夠用另外一種方法。

是由Floyd發明的一個算法,咱們舉例來講明這個聰明又有趣的算法

假設咱們在一個很長很長的圓形軌道上行走,咱們如何知道咱們已經走了一圈呢,固然咱們能夠像第一種方法那樣作

更聰明的方法是讓A和B按照B的速度是A的兩倍從同一塊兒點開始往前走,當B第一次遇上A時,(套圈,由於B在第一圈以內必定沒法和A相遇除非速度同樣)

咱們便知道B已經走了至少一圈。

因此咱們能夠把x看成B,y看成A來進行循環測試,具體實現詳見參考程序

 

 

 

先來講一下歐拉函數的線性篩法

咱們要證實的是其中要用到的一個結論,

若是i mod p==0,那麼phi(i*p)=p*phi(i)

========================

設P是素數,

 若p是x的約數,則E(x*p)=E(x)*p.

 若p不是x的約數,則E(x*p)=E(x)*E(p)=E(x)*(p-1).

證實以下:

E(x)表示比x小的且與x互質的正整數的個數。
*若p是素數,E(p)=p-1。
*E(p^k)=p^k-p^(k-1)=(p-1)*P^(k-1)
證:令n=p^k,小於n的正整數數共有n-1即(p^k-1)個,其中與p不質的數共[p^(k-1)-1]個(分別爲1*p,2*p,3*p...p(p^(k-1)-1))。
因此E(p^k)=(p^k-1)-(p^(k-1)-1)=p^k-p^(k-1).得證。
*若ab互質,則E(a*b)=E(a)*E(b),歐拉函數是積性函數.
*對任意數n均可以惟一分解成n=p1^a1*p2^a2*p3^a3*...*pn^an(pi爲素數).
則E(n)=E(p1^a1)*E(p2^a2)*E(p3^a3)*...*E(pn^an)     
      =(p1-1)*p1^(a1-1)*(p2-1)*p2^(a2-1)*...*(pn-1)*pn^(an-1)
      =(p1^a1*p2^a2*p3^a3*...*pn^an)*[(p1-1)*(p2-1)*(p3-1)*...*(pn-1)]/(p1*p2*p3*...*pn)
      =n*(1-1/p1)*(1-1/p2)*...*(1-1/pn)
* E(p^k)    =(p-1)*p^(k-1)=(p-1)*p^(k-2)*p
  E(p^(k-1))=(p-1)*p^(k-2)
->當k>1時,E(p^k)=E(p*p^(k-1))=E(p^(k-1))*p.
  (當k=1時,E(p)=p-1.)
由上式: 設P是素數,
  若p是x的約數,則E(x*p)=E(x)*p.
  若p不是x的約數,則E(x*p)=E(x)*E(p)=E(x)*(p-1).   證實結束。

咱們能夠取證實過程當中的一個結論。。那就是E(p^k)=E(p^(k-1))*p,實際上這是一個顯然但容易忽略的事實

爲何顯然呢,咱們知道E(p^k)=(p^k-1)-(p^(k-1)-1)=p^k-p^(k-1)=p*p^(k-1)-p^(k-1)=(p-1)*p^(k-1)

咱們只需提取一個p,變成(p-1)*p^(k-2)*p,顯然,E(p^(k-1))=(p-1)*p^(k-2),那麼就能夠寫成E(p^(k-1))*p,

前提是k>1,

而後若是i mod p==0,那麼i不斷對p取模,直到i%p!=0,i能夠寫成i=q*p^r

則E(i*p)=E(q*p^r*p)=E(q*p^(r+1)),咱們知道q和p^r互質(顯然),那麼固然q和p^(r+1)也互質

因此E(q*p^(r+1))=E(q)*E(p^(r+1)),運用截取的事實

E(q)*E(p^(r+1))=E(q)*E(p^r)*p,然而E(i)=E(q)*E(p^r)

因此E(q)*E(p^r)*p=E(i)*p,

則結論,E(i*p)=E(i)*p成立,證畢

這裏咱們考慮了在線性篩中i%pr[j]==0的狀況,互質的狀況呢

顯然若是沒有碰到i%pr[j]==0的狀況時,這個合數(質數就不用考慮了),尚未遇到和他最小的質因子相等的質數,那麼又惟一分解定理可知,這些狀況

兩個數都是互質的 

BabyStep-GiantStep 及擴展算法

有一個顯然可是容易忽略的事實,A>0,A若是不是C的倍數,A必定小於C,(若是C是質數那麼A和C必定互質)

先來了解一個概念:離散對數,離散對數是一種在整數中基於同餘運算和原根的對數運算。

原根就是。。

 

並非每個模都存在原根。。

當模m有原根時,設G爲模m時的一個原根,則當x=G^k(mod m)時,logG(x)=k(mod phi(m))由於G^(phi(m))=1,因此多於phi(m)的部分砍掉就行了,

Baby-Step Giant-Step 及 擴展算法 Extended BSGS

用來求解A^(x)=B(mod C)

(x>=0&&x<C)這樣的問題,

由於C是質數,若是A是C的倍數則B=0,不然A<C,則A,C互質

則A的冪次mod C有循環節(歐拉定理),因此x是這個範圍的

 

這個算法是以空間換時間,對窮舉算法的一個改進

原始的BSGS只能解決C爲素數的狀況

設m=sqrt(C)上取整,x=i*m+j,那麼A^x=(A^m)^i*A^j(i>=0&&i<m,j>=0&&j<m)

若是咱們枚舉i,j則這是sqrt(C)*sqrt(C)的,可是這樣咱們就枚舉出了全部的x,由此可知該枚舉方法的正確性

其實就是。。咱們須要枚舉小於sqrt(C)和大於sqrt(C)的狀況

可是咱們能夠只枚舉i,這是sqrt(C)級別的枚舉

 

對於一個枚舉出來的i,令D=(A^(m)^i),如今問題轉化爲了求D*A^j=B(mod C)

因爲A,C互質,則A的冪次也和C互質,因此至關於求Dx+Cy=B

而GCD(D,C)=1,因此B%(GCD(D,C))==0,因此x必定有解,即A^j必定有解

因此跑一遍擴展歐幾里得算法,咱們就能算出A^j是多少

 

求出了A^j,如今的問題就是我怎麼知道j是多少,一個很是聰明的方法是,先用sqrt(C)的時間

將A^j所有存進hash表裏面,而後查表只需O(1)就知道j是多少了,固然這裏是手工Hash的複雜度

若是你用map的話,大概是O(log(sqrt(C)))

消因子

關於消因子,是這樣的,

A=B(mod m)

那麼咱們能夠推出 A=B(mod mc)

 而後咱們又能夠推出

AC=BC(mod mc)

那麼因爲是充分必要條件,咱們也能夠反推回A=B(mod m)

咱們也能夠這麼想,A=B(mod m)

能夠看做是A=pm+r,B=qm+r,同餘嘛,r相同

那麼咱們能夠推出,AC=pCm+Cr,BC=qCm+Cr

這個能夠推出AC=BC(mod mC)

那麼若是AC,和mC有公因子,這個狀況顯然有公因子C嘛,因而咱們能夠消去公因子,那麼BC也要消去一樣的公因子C

那麼能夠推出,A=B(mod m)

 

 

擴展的BSGS不要求C是素數,大體的作法和原始的BSGS同樣

只是作一些修改,由於同餘具備一條性質

令d=GCD(A,C),A=a*d,B=b*d,C=c*d

則a*d=b*d(mod c*d)

等價於a=b(mod c)

所以開始前先消除因子

只要GCD(A,C)!=1,咱們就A,B,C都同除以GCD(A,C)

其中A不用真的除,咱們記錄一個D=1,每次D*=A/GCD(A,C),和乘法的次數cnt

在消除因子時若是GCD(A,C)!=1,且B%(GCD(A,C))!=0此時無解

爲何呢

假設a*d=k(mod c*d)

則a*d=q*c*d+k

顯然d能整除a*d,那麼d也能整除k,若是d不能整除k就無解

進一步分析咱們能夠知道假如A是小於d的,那麼K<d,(mod Cd)

假如A是d的倍數,那麼mod C*d是絕對不會剩下一個比d還小的數,

而且這個數必定是d的倍數,刨去單個的d,同理不會剩下比d小的數,因此必定是d的倍數,因此必定會被d整除

前提是A是d的倍數哦

 

執行完上面的過程,問題變成了,D*A^(x-cnt)=B(mod C)

令x=i*m+j+cnt

後面作法就跟BSGS同樣了。

可是注意到i>=0,j>=0,咱們明顯存在小於等於cnt的狀況,

因此在消因子以前須要作一次log(C)的枚舉,直接驗證A^i%C=B

聽說這樣是要考慮到ρ型軌道,問題來了,,軌道是什麼呢

那個軌道是這樣,由於n^x mod p 的值最終會產生循環,因此你能夠想象各類軌道就好像循環的鏈表!

 

階:知足 x r ≡ 1 (mod m) 最小正整數 r 稱爲 x 的階 ordm(x) ,不可貴到 ordm(x) | ϕ(m)

由於phi(m)是循環節結尾,若是有比phi(m)小的循環節尾,那麼那個數必定能夠整除phi(m)

 

 斷定a是否爲x的原根

枚舉 phi(x) 的因子,熟知階是 phi(x) 的因子, 

 可是你發現若是某個 a^(phi(x)/(prime factor of phi(x))) 是 1

就存在某個 <phi(x) 的因子是階
就不是原根了
因此咱們在log(phi(x))的時間裏可以判別a是不是x的原根
 

1、枚舉

從2開始枚舉,而後暴力判斷g^(P-1) = 1 (mod P)是否當且當指數爲P-1的時候成立

而因爲原根通常都不大,因此能夠暴力獲得.

2、講究方法

例如求任何一個質數x的任何一個原根,通常就是枚舉2到x-1,並檢驗。有一個方便的方法就是,求出x-1全部不一樣的質因子p1,p2...pm,對於任何2<=a<=x-1,斷定a是否爲x的原根,只須要檢驗a^((x-1)/p1),a^((x-1)/p2),...a^((x-1)/pm)這m個數中,是否存在一個數mod x爲1,若存在,a不是x的原根,不然就是x的原根。

原來的複雜度是O(P-1),如今變成O(m)*log(P-1)m爲x-1質因子的個數。很明顯質因子的個數遠遠小於x-1。

證實可用歐拉定理裴蜀定理

 

說明了對任何整數a、b和它們的最大公約數d,關於未知數x和y的線性丟番圖方程(稱爲裴蜀等式):

ax + by = m 
有解當且僅當m是d的倍數。裴蜀等式有解時必然有無窮多個整數解,每組解x、y都稱爲裴蜀數,可用展轉相除法求得。

例如,12和42的最大公因子是6,則方程12x + 42y = 6有解。事實上有(-3)×12 + 1×42 = 6及4×12 + (-1)×42 = 6。

特別來講,方程 ax + by = 1 有解當且僅當整數a和b互素。

裴蜀等式也能夠用來給最大公約數定義:d其實就是最小的能夠寫成ax + by形式的正整數。這個定義的本質是整環中「理想」的概念。所以對於多項式整環也有相應的裴蜀定理。

那我來把下面的證實囉嗦地說一遍吧,防止有的同窗看不懂了。

 1 假設x-1能夠分解爲p1~pm的冪次,Si=(x-1)/pi;
那麼假設a的S1~Sm冪次存在一個等於1的數,那麼顯然這個不是咱們要的答案,由於他構成互不相同的元素集合
2 那麼若是a的S1~Sm次方都沒有等於1的,此時咱們用反證法來證實再沒有因子能使得a的冪次等於1 3 假設存在一個t<phi(x)=x-1使得a^t = 1 (mod x) 4 5 由裴蜀定理,必定存在一組k,r使得kt=(x-1)r+gcd(t,x-1) 6 7 由歐拉定理有,a^(x-1) = 1 (mod x) 8 9 因而由上述三個等式 1 = a^(kt) = a^(xr-r+gcd(t,x-1)) = a^gcd(t,x-1) (mod x) 10 11 而t<x-1故gcd(t,x-1)<x-1 12 (而咱們知道一個數被分解質因數以後,他的因子必能寫成他的質因子的乘積,故因子最小爲p1~pm
因此比x-1小的儘可能包含儘量多因數的狀況最多有多少種呢,顯然讓他減去最小的質因子的一個冪次就能夠也就是,x-1/pi) 13 又gcd(t,x-1)|x-1 因而gcd(t,x-1)必整除(x-1)/p1,(x-1)/p2...(x-1)/pm其中至少一個,設其一爲(x-1)/pi 14 15 那麼a^((x-1)/pi) = (a^gcd(t,x-1))^s = 1^s = 1 (mod x) 16 17 那麼這個假設與Si中沒有能使a^Si=1的前提矛盾,故,在任意a^Si!=1時,再也沒有比x-1小的數t能使a^t=1

這裏的存在是說。。那m個數中是否有一個是mod =1

反證法很明白。。對於裴蜀定理。。這個是無條件成立的。。任意兩個數都能找到,pa+qb=gcd(a,b)

而後咱們爲何只枚舉這m個數呢。。由於這是m個最大的約數的狀況,這些狀況包含了phi(x)的最小的因子的冪次的全部狀況

若是枚舉了phi(x)/pi那麼就沒有必要枚舉phi(x)/pi^2,由於若是phi(x)/pi能檢測出來mod以後等於1,那麼phi(x)/pi^2就不用檢測

若是不能檢測的話,那麼後面那個也是不能檢測的。。

相關文章
相關標籤/搜索