• <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ò)展歐幾里德算法

            歐幾里德算法
            歐幾里德算法又稱輾轉(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è)原理來做的,其算法用C++語言描述為:

            int Gcd(int a, int b)
            {
                
            if(b == 0)
                    
            return a;
                
            return Gcd(b, a % b);
            }

            當(dāng)然你也可以寫成迭代形式:
            int Gcd(int a, int b)
            {
                
            while(b != 0)
                
            {
                    
            int r = b;
                    b 
            = a % b;
                    a 
            = r;
                }

                
            return a;
            }

            本質(zhì)上都是用的上面那個(gè)原理。

            補(bǔ)充: 擴(kuò)展歐幾里德算法是用來在已知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賦值過程,這就是擴(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ì)語言中的除法)
            那么可以得到:
            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)算法,他無論從理論還是從效率上都是很好的。但是他有一個(gè)致命的缺陷,這個(gè)缺陷只有在大素?cái)?shù)時(shí)才會(huì)顯現(xiàn)出來。

            考慮現(xiàn)在的硬件平臺(tái),一般整數(shù)最多也就是64位,對(duì)于這樣的整數(shù),計(jì)算兩個(gè)數(shù)之間的模是很簡單的。對(duì)于字長為32位的平臺(tái),計(jì)算兩個(gè)不超過32位的整數(shù)的模,只需要一個(gè)指令周期,而計(jì)算64位以下的整數(shù)模,也不過幾個(gè)周期而已。但是對(duì)于更大的素?cái)?shù),這樣的計(jì)算過程就不得不由用戶來設(shè)計(jì),為了計(jì)算兩個(gè)超過 64位的整數(shù)的模,用戶也許不得不采用類似于多位數(shù)除法手算過程中的試商法,這個(gè)過程不但復(fù)雜,而且消耗了很多CPU時(shí)間。對(duì)于現(xiàn)代密碼算法,要求計(jì)算 128位以上的素?cái)?shù)的情況比比皆是,設(shè)計(jì)這樣的程序迫切希望能夠拋棄除法和取模。 (注:說到拋棄除法和取模,其實(shí)輾轉(zhuǎn)相除法可以寫成減法的形式)

            Stein算法由J. Stein 1961年提出,這個(gè)方法也是計(jì)算兩個(gè)數(shù)的最大公約數(shù)。和歐幾里德算法 算法不同的是,Stein算法只有整數(shù)的移位和加減法,這對(duì)于程序設(shè)計(jì)者是一個(gè)福音。

            為了說明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í),說明兩個(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));
            }

            考慮歐幾里德算法,最惡劣的情況是,每次迭代a = 2b -1,這樣,迭代后,r= b-1。如果a小于2N,這樣大約需要 4N次迭代。而考慮Stein算法,每次迭代后,顯然AN+1BN+1≤ ANBN/2,最大迭代次數(shù)也不超過4N次。也就是說,迭代次數(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í)也沒啥好整理的,網(wǎng)上很多資料了,就當(dāng)備用把:-)
            posted on 2009-05-31 19:09 chatler 閱讀(5477) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Algorithm
            <2009年12月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            常用鏈接

            留言簿(10)

            隨筆分類(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

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

            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)論排行榜

            亚洲欧洲日产国码无码久久99| 一级做a爰片久久毛片人呢| 18岁日韩内射颜射午夜久久成人| 久久久一本精品99久久精品88| 亚洲av成人无码久久精品| 久久中文骚妇内射| 岛国搬运www久久| 欧美精品九九99久久在观看| 人妻少妇久久中文字幕| 日韩精品国产自在久久现线拍| 久久久精品无码专区不卡| 国产偷久久久精品专区| 青青青国产精品国产精品久久久久 | 无码专区久久综合久中文字幕 | 久久人人爽人人爽人人AV东京热 | www.久久99| 久久婷婷五月综合成人D啪| 欧美亚洲色综久久精品国产| 2020最新久久久视精品爱| 精品国产青草久久久久福利| 国产毛片久久久久久国产毛片| 久久精品国产亚洲AV不卡| 狠狠色综合久久久久尤物| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 久久天天躁夜夜躁狠狠躁2022| 久久福利青草精品资源站免费| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 久久精品国产男包| 国产高潮国产高潮久久久91 | 精品国产乱码久久久久久1区2区| 无码精品久久一区二区三区| 伊人丁香狠狠色综合久久| 日日躁夜夜躁狠狠久久AV| 亚洲国产成人精品久久久国产成人一区二区三区综 | 国产精品99久久久久久www| 久久久久无码精品国产| 日韩影院久久| 久久久久无码精品| 日韩欧美亚洲综合久久影院d3| 久久夜色精品国产噜噜麻豆| 2021久久精品免费观看|