1. 程式人生 > >歐幾裏得算法(含嚴謹證明)

歐幾裏得算法(含嚴謹證明)

iostream char code using cout har 不可 dig 也有

gcd(gong chan dang)(greatest common divisor) 最大公約數,指兩個整數所有公共約數中最大的。

首先先上結論,求最大公約數,我們可以通過遞歸gcd(a,b)=gcd(b,a%b),gcd(a,0)=a計算,復雜度是logn

很明顯,這個偉大的結論gcd(a,b)=gcd(b,a%b),就是著名的歐幾裏得公式。

那麽怎麽證,其實還挺簡單的。我們把證明分為兩步驟:

    1、證明gcd(a,b)是b,a%b的一個公約數

    2、證明這個公約數是最大的。

1、我們設gcd(a,b)=d,再令a=k1*d,b=k2*d.

我們再設,a=k*b+c(也就是a除以b商k余c),那麽c就是余數,也就是a%b.

講上面那個式子移項,得到c=a-k*b,然後再把a=k1*d,b=k2*d,這兩個式子裏的a、b帶入式子,得到:

c=k1*d-k*k2*d,在提取公因數d,得到c=(k1-k*k2)*d.這樣就說明,c,也就是a%b有d這個約數,因為開始我們設b也有d這個約數,所以gcd(a,b)是b,a%b的一個公約數。

2、現在知道了它是一個公約數,那麽怎麽證它是最大的?(其實感性分析,a%b都變小了,公約數不可能更大呀!)

  但是術學是一門嚴謹的學科,我們要嚴謹證明。我們知道,c(a%b)=(k1-k*k2)*d,b=k2*d,我們只需要證明k1-k*k2、k2互質就好了。

這裏可以用到反證法:我們假設k1-k*k2=q*t,k2=p*t,並且t>1(也就是那兩個不互質)。

我們將前面那個式子移項,得到k1=q*t+k*k2,再把這個k1代到最開始的a=k1*d,得到a=(q*t+k*k2)*d,再利用乘法分配律,得到:

  a=q*t*d+k*k2*d,我們這時發現,k2*d不就是最開始的b嗎?,將其帶入,得到:a=q*t*d+b*d.

  這時,我們再把k2=p*t代入開始的b=k2*d,得到b=p*t*d,再把這個式子代到a=q*t*d+b*d.得到了:a=q*t*d+p*t*d.提取公因數:a=(q+p)*t*d

  現在,再和b=p*t*d比較,發現他們的最大公因數變成了t*d和開始矛盾,所以假設不成立,反證成功!

好吧,還是貼一下求最大公約數的代碼吧

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define REP(i,k,n)  for(int i=k;i<=n;i++)
#define in(a) a=read()
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch==-)
            f=-1;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-0;
    return x*f;
}
inline int gcd(int a,int b){
    if(b==0)  return a;
    return gcd(b,a%b);
}
int main(){
    int a,b;
    in(a),in(b);
    cout<<gcd(a,b);
}

歐幾裏得算法(含嚴謹證明)