歐幾里得 & 拓展歐幾里得演算法 講解 (Euclid & Extend- Euclid Algorithm)
歐幾里得& 拓展歐幾里得(Euclid & Extend-Euclid)
歐幾里得演算法(Euclid)
背景:
歐幾里德演算法又稱輾轉相除法,用於計算兩個正整數a,b的最大公約數。 ——百度百科
程式碼:
遞推的程式碼是相當的簡潔:
int gcd(int a,int b) { return b == 0 ? a : gcd(b, a % b); }
分析:
方法說了是輾轉相除法,自然沒有什麼好介紹的了。。
Fresh肯定會覺得這樣遞迴下去會不會爆棧?實際上在這裡是不會爆棧的,因為遞迴的層數是非常小的,不信你可以隨便拿一些大數測試一下,lrj的白書和紫書上講到gcd函式的遞迴層數不超過40785lgN + 1.6723,其中N=max{a,b}。讓gcd函式遞迴層數最多的是gcd(F(n),F(n-1)),F(n)是Fibonacci數!!至於為什麼博主沒有證明,有想法的小夥伴麻煩在評論在說下下,(*^__^*) 嘻嘻……
拓展歐幾里得(Extend- Euclid)
背景:
擴充套件歐幾里德演算法是用來在已知a, b求解一組x,y [x,y都是整數],使它們滿足貝祖等式: ax+by = gcd(a, b) =d
用到的幾個歐幾里得重要結論:
1) gcd(a,b) = gcd(b,a %b);
2) gcd(a,0) = a.
程式碼:
typedef __int64 ll;
void exgcd(ll a, ll b, ll& d, ll& x, ll &y)
{
if(!b)
{
d = a, x = 1, y = 0;
}
else
{
exgcd(b, a % b, d, y, x);
y -= x * (a / b);
}
}
分析:
設如下兩個方程:
ax+by = gcd(a,b) = d;
bx’+(a%b)y’ = gcd(b,a%b);
那麼由重要結論(1)有gcd(a,b) = gcd(b,a %b),
那麼ax+by = bx’+(a%b)y’ = bx’ +(a – [a/b]*b)y’ = ay’ + b(x’ – [a/b]y’),
由恆等關係有: x = y’ , y = (x’ – [a/b]y’),[a/b]表示a/b的值向下取整。
........
那麼現在就可以用exgcd(a,b,d,x,y)表示方程ax+by = d,那麼由上面一直遞迴下去,直到 b = 0,遞迴結束,此時 d = gcd(a,0) =a , x = 1,y =0;【因為 ax+0*y = gcd(a,0)嘛~】
拓展歐幾里得的幾個應用
求解不定方程
例如:求解不定整數方程ax+by = c
求ax+by = c, 令d =gcd(a,b);
那麼(a / d ) * x + (b / d )* y = c / d
因為(a / d )、(b / d ) 、x、y都是整數,那麼保證原不定整數方程ax+by = c有解的充要條件就是c / d為整數,即c是gcd(a,b)的倍數。
如果有解,那麼令 K = c/d;
那麼,對方程aX+bY = d;假設有拓展歐幾里得求出一組解為(X0,Y0),那麼aX0+bY0 = d;等式兩邊同時乘以K,即K*( aX0+bY0 ) = d*K = c;由恆等關係,原方程的解(x0,y0):
X0 = KX0 = c/d * X0,y0 = KY0 = c/d *Y0。
不定方程的通解:
若(x0,y0)是不定整數方程ax+by = c的一組解,則他的任意整數解都可以表示成(x0+ kb’, y0-ka’),其中a’ = a/gcd(a,b), b’ = b/gcd(a,b).
例題:
求解模線性方程
方法跟上面類似,將同餘方程轉化為常規線性方程就可以了,跟上面一樣,談到同餘方程的一個解時,其實指的是一個同餘等價類....
具體內容待補充...
求模的逆元
待補充…