先感謝參考文獻:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html
注:以下討論的數均為整數
一、歐幾里得算法(重點是證明,對后續知識有用)
歐幾里得算法,也叫輾轉相除,簡稱 gcd,用於計算兩個整數的最大公約數
定義 gcd(a,b) 為整數 a 與 b 的最大公約數
引理:gcd(a,b)=gcd(b,a%b)
證明:
設 r=a%b , c=gcd(a,b)
則 a=xc , b=yc , 其中x , y互質
r=a%b=a-pb=xc-pyc=(x-py)c
而b=yc
可知:y 與 x-py 互質
證明:
假設 y 與 x-py 不互質
設 y=nk , x-py=mk , 且 k>1 (因為互質)
將 y 帶入可得
x-pnk=mk
x=(pn+m)k
則 a=xc=(pn+m)kc , b=yc=nkc
那么此時 a 與 b 的最大公約數為 kc 不為 k
與原命題矛盾,則 y 與 x-py 互質
因為 y 與 x-py 互質,所以 r 與 b 的最大公約數為 c
即 gcd(b,r)=c=gcd(a,b)
得證
當a%b=0時,gcd(a,b)=b
這樣我們可以寫成遞歸形式
1 inline int gcd(int a,int b) 2 { 3 return b?gcd(b,a%b):a; 4 }
模板題:http://codevs.cn/problem/1212/
二、擴展歐幾里得算法
擴展歐幾里得算法,簡稱 exgcd,一般用來求解不定方程,求解線性同余方程,求解模的逆元等
引理:存在 x , y 使得 gcd(a,b)=ax+by
證明:
當 b=0 時,gcd(a,b)=a,此時 x=1 , y=0
當 b!=0 時,
設 ax1+by1=gcd(a,b)=gcd(b,a%b)=bx2+(a%b)y2
又因 a%b=a-a/b*b
則 ax1+by1=bx2+(a-a/b*b)y2
ax1+by1=bx2+ay2-a/b*by2
ax1+by1=ay2+bx2-b*a/b*y2
ax1+by1=ay2+b(x2-a/b*y2)
解得 x1=y2 , y1=x2-a/b*y2
因為當 b=0 時存在 x , y 為最后一組解
而每一組的解可根據后一組得到
所以第一組的解 x , y 必然存在
得證
根據上面的證明,在實現的時候采用遞歸做法
先遞歸進入下一層,等到到達最后一層即 b=0 時就返回x=1 , y=0
再根據 x=y’ , y=x’-a/b/y’ ( x’ 與 y’ 為下一層的 x 與 y ) 得到當層的解
不斷算出當層的解並返回,最終返回至第一層,得到原解
1 inline void exgcd(int a,int b) 2 { 3 if (b) 4 { 5 exgcd(b,a%b); 6 int k=x; 7 x=y; 8 y=k-a/b*y; 9 } 10 else y=(x=1)-1; 11 }
三、exgcd 解不定方程(使用不將a與b轉為互質的方法)
對於 ax+by=c 的不定方程,設 r=gcd(a,b)
當 c%r!=0 時無整數解
當 c%r=0 時,將方程右邊 *r/c 后轉換為 ax+by=r 的形式
可以根據擴展歐幾里得算法求得一組整數解 x0 , y0
而這只是轉換后的方程的解,原方程的一組解應再 *c/r 轉變回去
(如 2x+4y=4 轉換為 2x+4y=2 后應再將解得的 x , y 乘上2)
則原方程解為 x1=x0*c/r , y1=x0*c/r
通解 x=x1+b/r*t , y=y1-a/r*t ,其中 t 為整數
證明:
將 x , y 帶入方程得
ax+ab/r*t+by-ab/r*t=c
ax+by=c
此等式恆成立
得證
這里 b/r 與 a/r 為最小的系數,所以求得的解是最多最全面的
證明:
為了推出證明中的 ax+by=c ,且想達到更小的系數,只能將 b/r 與 a/r 同除以一個數 s
而 b/r 與 a/r 互質,且 s 為整數,則 s=1 ,不影響通解
那么 b/r 與 a/r 就為最小的系數
得證
模板題:http://www.cnblogs.com/hadilo/p/5917173.html
四、exgcd 解線性同余方程
關於 x 的模方程 ax%b=c 的解
方程轉換為 ax+by=c 其中 y 一般為非正整數
則問題變為用 exgcd 解不定方程
解得 x1=x0*c/r
通解為 x=x1+b/r*t
設 s=b/r (已證明 b/r 為通解的最小間隔)
則 x 的最小正整數解為 (x1%s+s)%s
證明:
若 x1>0,則 (x1%s+s)%s=x1%s%s+s%s=x1%s=x1-ts (t∈N)
若 x1<0,因在 C++ 里 a%b=-(-a%b)<0 (a<0 , b>0) 如 -10%4=-2
則 (x1%s+s)%s=(-(-x1%s)+s)%s=(-(ts-x1)+s)%s=ts-x1 (t∈N)
即為 x1 通過加或減上若干個 s 后得到的最小正整數解
得證
亦可偽證 x1<0 的情況:設 x1=-5 , s=2
則 (x1%s+s)%s=(-5%2+2)%2=(-1+2)%2=3%2=1
即為 x1 加上 3 個 s 后的到的最小正整數解
模板題:http://www.cnblogs.com/hadilo/p/5951091.html
版權所有,轉載請聯系作者,違者必究