小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

最大公約數(shù)(Gcd)兩種算法(Euclid && Stein) [整理]

 herowuking 2015-06-16
很老的東東了,其實(shí)也沒(méi)啥好整理的,網(wǎng)上很多資料了,就當(dāng)備用把:-)



1. 歐幾里德算法和擴(kuò)展歐幾里德算法

歐幾里德算法

歐幾里德算法又稱輾轉(zhuǎn)相除法,用于計(jì)算兩個(gè)整數(shù)a,b的最大公約數(shù)。其計(jì)算原理依賴于下面的定理:


定理:gcd(a,b) = gcd(b,a mod b)


證明:a可以表示成a = kb + r,則r = a mod b

假設(shè)d是a,b的一個(gè)公約數(shù),則有

d|a, d|b,而r = a - kb,因此d|r

因此d是(b,a mod b)的公約數(shù)


假設(shè)d 是(b,a mod b)的公約數(shù),則

d | b , d |r ,但是a = kb +r

因此d也是(a,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é)束

如果B=0,A是最大公約數(shù),算法結(jié)束

設(shè)置A1 = A、B1=B和C1 = 1

如果An和Bn都是偶數(shù),則An+1 =An /2,Bn+1 =Bn /2,Cn+1 =Cn *2(注意,乘2只要把整數(shù)左移一位即可,除2只要把整數(shù)右移一位即可)

如果An是偶數(shù),Bn不是偶數(shù),則An+1 =An /2,Bn+1 =Bn ,Cn+1 =Cn (很顯然啦,2不是奇數(shù)的約數(shù))

如果Bn是偶數(shù),An不是偶數(shù),則Bn+1 =Bn /2,An+1 =An ,Cn+1 =Cn (很顯然啦,2不是奇數(shù)的約數(shù))

如果An和Bn都不是偶數(shù),則An+1 =|An -Bn|,Bn+1 =min(An,Bn),Cn+1 =Cn

n++,轉(zhuǎn)4

這個(gè)算法的原理很顯然,所以就不再證明了?,F(xiàn)在考察一下該算法和歐幾里德方法效率上的差別。


給出一個(gè)C++的實(shí)現(xiàn):


int Gcd(int a, int b)

{

    
if(a == 0return b;

    
if(b == 0return a;

    
if(a % 2 == 0 && b % 2 == 0return 2 * gcd(a >> 1, b >> 1);

    
else if(a % 2 == 0)  return gcd(a >> 1, b);

    
else if(b % 2 == 0return gcd(a, b >> 1);

    
else return gcd(abs(a - b), Min(a, b));

}



考慮歐幾里德算法,最惡劣的情況是,每次迭代a = 2b -1,這樣,迭代后,r= b-1。如果a小于2N,這樣大約需要 4N次迭代。而考慮Stein算法,每次迭代后,顯然AN+1BN+1≤ ANBN/2,最大迭代次數(shù)也不超過(guò)4N次。也就是說(shuō),迭代次數(shù)幾乎是相等的。但是,需要注意的是,對(duì)于大素?cái)?shù),試商法將使每次迭代都更復(fù)雜,因此對(duì)于大素?cái)?shù)Stein將更有優(yōu)勢(shì)



練習(xí):

OJ上面的赤裸裸的Gcd算法的題不多,大多都是套了一個(gè)外殼。

找了兩道,可以試試看

HDOJ 2028 Lowest Common Multiple Plus   這個(gè)是求n個(gè)數(shù)的最小公倍數(shù)(有了最大公約數(shù),最小公倍數(shù)應(yīng)該很容易了)

ZJU 2678 Bishops on a Toral Board  這個(gè)題目要發(fā)現(xiàn)規(guī)律,不錯(cuò)的題目

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多