1. 程式人生 > >歐幾里得演算法的推導與證明 || 擴充套件歐幾里德演算法的解釋說明

歐幾里得演算法的推導與證明 || 擴充套件歐幾里德演算法的解釋說明

序言:

     當博主第一次見到歐幾里德演算法時,我是不屑一顧的,由於模板比較好背,所以也沒有仔細研究過其中的數學原理.這段時間突然喜歡上了數學,碰巧同學講了一下基礎數論,就去聽了一聽. 由於博主數學基礎和學習能力都比較差,沒有立即消化其中的知識,於是研究了好幾天,直到今天才有所進展,通過這篇部落格希望大家能夠認識到數學的精妙之處.

正文:

歐幾里德演算法的推導與證明:

     眾所周知,歐幾里德演算法的定理可以表示為:
                                                      gcd(

a,b)=gcd(b,a%b)
     但是這個定理是如何推匯出來的呢?

首先我們可以假設a=kb+r(其中的r代表著a/b的餘數,也就是a%b的結果)

  1.首先我們假設d是a和b的最大公約數,則我們可以知道 a可以整除d,表示為a|b,b也可以整除d,表示為b|d,由於r=akb 其中a是d的倍數,而且b也是d的倍數,那我們可以得到其實r也是d的倍數,換句話說r也是可以整除d.

  2.接下來我們假設d是b和r的最大公約數,則我們可以知道b可以整除d,表示為b|d,r也可以整除d,表示為r|d,由於a=kb+r其中b是d的倍數,而且r也是d的倍數,那我們可以得知其實a也是d的倍數,換句話說a也是可以整除d.

通過以上的充分必要式的證明方法,我們可以得到:gcd(a,b)=gcd(b,a%b)

接下來我們來看程式碼實現(遞迴) :

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

看起來十分簡單,實則暗藏玄機…
首先我們需要考慮當 b=0 時,為何要返回a呢.. 在解釋之前,我要說明一點,只有當a > b時 演算法才算正式開始進行運算,這是為什麼呢?我們舉個簡單的例子,當 a=12,b

=16 時,我們在第二輪的時候驚奇的發現他遞迴的卻是 gcd(16,12) ,這其實算是一種維護的過程,感嘆第一寫出這份程式碼人心思的縝密….迴歸正題,當我們發現 b=0 時,也就是說上一輪的 a%b=0 也就是說上一輪的a可以完全整除b,此輪的a則是上一輪的b提供的,所以將b返回即可。

我遇到的問題

在學習歐幾里得的時候,我有一個疑惑,在我們剛才的推導過程:假設d是a和b的最大公約數,我們可以推匯出 r (a%b)也可以整除d , 既然a,b,r都可以整除d,為什麼我們的等式只能寫作 gcd(a,b)=gcd(b,a%b) 而不能寫作 gcd(a,b)=gcd(a,a%b) 呢? 在這個問題上,我思考了很久,終於得到了一定的理解… 首先我剛才說過 只有當 a>b 的時候,演算法才開始進行運算,所以說a在這裡面是相對是最大的,b其次,而r是最小的…. 我說的可能太過絕對,以下為他們的具體關係:

                                                                 abr

在我們每輪遞迴的過程中,希望值是越來越小的…其中a確永遠是最大的…而且遞迴a也是沒有意義的…因為我們最終要求的是最大公約數解.

代數形式的推導過程:

這裡寫圖片描述
擴充套件歐幾里德演算法的解釋說明:

    在學習完上面所講的歐幾里德演算法之後,本節我們來講一下 擴充套件歐幾里得演算法,歐幾里德演算法是用來做什麼的呢?
    擴充套件歐幾里德演算法是用來在已知a, b求解一組x,y,使它們滿足貝祖等式: ax+by=gcd(a,b),然後再求出現實所所需要的通解。由於證明這個等式成立的過程涉及到其他的數論知識,在學習基礎的我們可以暫時把證明過程放在一邊,權當這是成立的。

我們已知 ax1+by1=gcd(a,b) 根據歐幾里德,我們可以得到:

                                        gcd(a,b)=gcd(b,a%b)

gcd(b,a%b)=bx2+(a%b)y2=bx2+(afloor(a/b)b)y2
我們最終可以得到:
y1=x2floor(a/b)y2,x1=y2

接下來我們來看程式碼實現(遞迴) :

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;
    y=t-a/b*y;
    return r;
}

現在我們考慮一下遞迴的終點…..當 b=0 我們為何要