很老的東東了,其實(shí)也沒(méi)啥好整理的,網(wǎng)上很多資料了,就當(dāng)備用把:-) 1. 歐幾里德算法和擴(kuò)展歐幾里德算法 歐幾里德算法 定理:gcd(a,b) = gcd(b,a mod b) 證明:a可以表示成a = kb + r,則r = a mod b 假設(shè)d 是(b,a mod b)的公約數(shù),則 因此(a,b)和(b,a mod b)的公約數(shù)是一樣的,其最大公約數(shù)也必然相等,得證 歐幾里德算法就是根據(jù)這個(gè)原理來(lái)做的,其算法用C++語(yǔ)言描述為: int Gcd(int a, int b) { if(b == 0) return a; return Gcd(b, a % b); } 當(dāng)然你也可以寫(xiě)成迭代形式: int Gcd(int a, int b) { while(b != 0) { int r = b; b = a % b; a = r; } return a; } 本質(zhì)上都是用的上面那個(gè)原理。 補(bǔ)充: 擴(kuò)展歐幾里德算法是用來(lái)在已知a, b求解一組p,q使得p * a+q * b = Gcd(a, b) (解一定存在,根據(jù)數(shù)論中的相關(guān)定理)。擴(kuò)展歐幾里德常用在求解模線性方程及方程組中。下面是一個(gè)使用C++的實(shí)現(xiàn): int exGcd(int a, int b, int &x, int &y) { if(b == 0) { x = 1; y = 0; return a; } int r = exGcd(b, a % b, x, y); int t = x; x = y; y = t - a / b * y; return r; } 把這個(gè)實(shí)現(xiàn)和Gcd的遞歸實(shí)現(xiàn)相比,發(fā)現(xiàn)多了下面的x,y賦值過(guò)程,這就是擴(kuò)展歐幾里德算法的精髓。 可以這樣思考: 對(duì)于a' = b, b' = a % b 而言,我們求得 x, y使得 a'x + b'y = Gcd(a', b') 由于b' = a % b = a - a / b * b (注:這里的/是程序設(shè)計(jì)語(yǔ)言中的除法) 那么可以得到: a'x + b'y = Gcd(a', b') ===> bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===> ay +b(x - a / b*y) = Gcd(a, b) 因此對(duì)于a和b而言,他們的相對(duì)應(yīng)的p,q分別是 y和(x-a/b*y) 2. Stein算法 歐幾里德算法是計(jì)算兩個(gè)數(shù)最大公約數(shù)的傳統(tǒng)算法,他無(wú)論從理論還是從效率上都是很好的。但是他有一個(gè)致命的缺陷,這個(gè)缺陷只有在大素?cái)?shù)時(shí)才會(huì)顯現(xiàn)出來(lái)。 考慮現(xiàn)在的硬件平臺(tái),一般整數(shù)最多也就是64位,對(duì)于這樣的整數(shù),計(jì)算兩個(gè)數(shù)之間的模是很簡(jiǎn)單的。對(duì)于字長(zhǎng)為32位的平臺(tái),計(jì)算兩個(gè)不超過(guò)32位的整數(shù)的模,只需要一個(gè)指令周期,而計(jì)算64位以下的整數(shù)模,也不過(guò)幾個(gè)周期而已。但是對(duì)于更大的素?cái)?shù),這樣的計(jì)算過(guò)程就不得不由用戶來(lái)設(shè)計(jì),為了計(jì)算兩個(gè)超過(guò)64位的整數(shù)的模,用戶也許不得不采用類似于多位數(shù)除法手算過(guò)程中的試商法,這個(gè)過(guò)程不但復(fù)雜,而且消耗了很多CPU時(shí)間。對(duì)于現(xiàn)代密碼算法,要求計(jì)算128位以上的素?cái)?shù)的情況比比皆是,設(shè)計(jì)這樣的程序迫切希望能夠拋棄除法和取模。 (注:說(shuō)到拋棄除法和取模,其實(shí)輾轉(zhuǎn)相除法可以寫(xiě)成減法的形式) Stein算法由J. Stein 1961年提出,這個(gè)方法也是計(jì)算兩個(gè)數(shù)的最大公約數(shù)。和歐幾里德算法 算法不同的是,Stein算法只有整數(shù)的移位和加減法,這對(duì)于程序設(shè)計(jì)者是一個(gè)福音。 為了說(shuō)明Stein算法的正確性,首先必須注意到以下結(jié)論: gcd(a,a) = a,也就是一個(gè)數(shù)和他自身的公約數(shù)是其自身 gcd(ka,kb) = k gcd(a,b),也就是最大公約數(shù)運(yùn)算和倍乘運(yùn)算可以交換,特殊的,當(dāng)k=2時(shí),說(shuō)明兩個(gè)偶數(shù)的最大公約數(shù)必然能被2整除。 有了上述規(guī)律就可以給出Stein算法如下: 如果A=0,B是最大公約數(shù),算法結(jié)束 給出一個(gè)C++的實(shí)現(xiàn): int Gcd(int a, int b) { if(a == 0) return b; if(b == 0) return a; if(a % 2 == 0 && b % 2 == 0) return 2 * gcd(a >> 1, b >> 1); else if(a % 2 == 0) return gcd(a >> 1, b); else if(b % 2 == 0) return gcd(a, b >> 1); else return gcd(abs(a - b), Min(a, b)); }
|
|
來(lái)自: herowuking > 《VC》