• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 297,  comments - 15,  trackbacks - 0
            轉(zhuǎn)自:::::http://blog.chinaunix.net/u2/76292/showart_1418158.html
            1. 歐幾里德算法和擴(kuò)展歐幾里德算法

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

            定理: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ò)程就不得不由用戶(hù)來(lái)設(shè)計(jì),為了計(jì)算兩個(gè)超過(guò) 64位的整數(shù)的模,用戶(hù)也許不得不采用類(lèi)似于多位數(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è)算法的原理很顯然,所以就不再證明了。現(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));
            }

            考慮歐幾里德算法,最?lèi)毫拥那闆r是,每次迭代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ò)的題目很老的東東了,其實(shí)也沒(méi)啥好整理的,網(wǎng)上很多資料了,就當(dāng)備用把:-)
            posted on 2009-05-31 19:09 chatler 閱讀(5497) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): Algorithm
            <2009年11月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(10)

            隨筆分類(lèi)(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

            • cloudward
            • 感覺(jué)這個(gè)博客還是不錯(cuò),雖然做的東西和我不大相關(guān),覺(jué)得看看還是有好處的

            network

            OSS

            • Google Android
            • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
            • os161 file list

            overall

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久热这里只有精品在线观看| 久久午夜综合久久| 18禁黄久久久AAA片| 久久婷婷成人综合色综合| 国产精品久久久亚洲| 久久亚洲中文字幕精品一区| 精品人妻伦九区久久AAA片69| 久久精品国产只有精品2020| 久久久久久午夜精品| 久久se这里只有精品| 久久综合九色综合网站| 久久青青草视频| 一级做a爰片久久毛片免费陪| 99久久久精品免费观看国产| 精品国产青草久久久久福利| 无码8090精品久久一区| 久久精品国产欧美日韩| 精品久久久久久99人妻| 国产精品99久久久久久猫咪| 777久久精品一区二区三区无码| 久久久精品国产sm调教网站| 久久亚洲AV成人无码国产| 国产A三级久久精品| 国产精品福利一区二区久久| 777米奇久久最新地址| 香港aa三级久久三级| 99久久这里只精品国产免费| 亚洲AV无码1区2区久久| 免费精品99久久国产综合精品| 久久九九亚洲精品| av色综合久久天堂av色综合在| 久久久久久久97| 国内精品久久久久影院网站| 久久综合色区| 日本免费久久久久久久网站| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 国产aⅴ激情无码久久| 精品久久久久久久久久中文字幕| 久久亚洲中文字幕精品一区| 久久精品天天中文字幕人妻| 国产成人精品久久|