擴展歐幾里得算法

給定兩個正整數m和n,咱們計算它們的最大公因子d和兩個整數a和b,使得a*m+b*n=d算法

算法流程

  E1.置a'=b=1;a=b'=0;c=m,d=n;ide

  E2.計算d和r,使得c=q*d+r;spa

  E3.若r==0;則退出,當前已有a*m+b*n=d;code

  E4;c=d;d=r;t=a';a'=a;a=t-q*a;t=b';b'=b;b=t-q*b;返回E2.blog

證實

 遞歸版本:遞歸

  對於已有的m和n,假設m>n;若是刨除變量a,b,a',b';算法與歐幾里得算法徹底同樣,爲計算最大公約數的算法.數學

  最終要求的爲a*m+b*n=d=GCD(m,n);若是改式子成立由歐幾里得算法可推出a'*n+b'*(m%n)=GCD(n,m%n);event

  由於GCD(m,n)=GCD(n,m%n);class

  因此a*m+b*n=a'*n+b'*(m%n)變量

        =a'*n+b'*(m-(m/n)*n)

        =a'*n+b'*m-b'*(m/n)*n

        =b'*m+(a'-b'*(m/n))*n

  因此a=b';b=a'-b'*(m/n);

  能夠推出根據a‘、b'能夠計算a、b。

  非遞歸版本:

  設m爲r[0],n=r[-1];根據歐幾里得算法可推出

  r[i-2]=r[i-1]*q[i]+r[i]; r=1...n+1;         (1)

  r[i](r=1...n+1)爲每次迭代的餘數,可知r[n+1]=0;且r[n]=GCD(m,n);

  因爲每一個r都是前兩個r的組合,因此對於a*m+b*n=GCD(m,n)存在(可用數學概括法證實):

  a[i]*m+b[i]*n=r[i];              (2)

  當i==1時,根據(1)(2)式

    a[1]*m+b[1]*n=r[1]

          =r[-1]-r[0]*q[1]

          =n-q[1]*m

  可推出:a[1]=-q[1],b[1]=1;

  當i==2時,根據(1)(2)式

    a[2]*m+b[2]*n=r[2]

          =r[0]-r[1]*q[2]

          =r[0]-(a[1]*m+b[1]*n)*q[2]

          =m-a[1]*q[2]*m-b[1]*q[2]*n

          =(1-a[1]*q[2])*m-b[1]*q[2]*n

  可推出:a[2]=1-a[1]*q[2],b[2]=-b[1]*q[2];

  當i>=3時,根據(1)(2)式

    a[i]*m+b[i]*n=r[i]

          =-q[i](a[i-1]*m+b[i-1]*n)+(a[i-2]*m+b[i-2]*n)

          =(-q[i]*a[i-1]+a[i-2])*m+(-q[i]*b[i-1]+b[i-2])*n

  對於i>=3,a[i]=-q[i]*a[i-1]+a[i-2],b[i]=-q[i]*b[i-1]+b[i-2];

  當咱們定義:a[-1]=0,a[0]=1,b[-1]=1,b[0]=0時,可構造出a,b的公式

    a[-1]=0,a[0]=1,a[i]=-q[i]*a[i-1]+a[i-2](i>=1)

    b[-1]=1,b[0]=0,b[i]=-q[i]*b[i-1]+b[i-2](i>=1)

代碼實現

void EGCD(int m,int n)
{
    int a,a1,b,b1,c,d,q,r,t;
    a1=b=1,a=b1=0,c=m,d=n;
    while(1)
    {
        q=c/d,r=c%d;
        if(r==0)
        {
            printf("(%d)*%d+(%d)*%d=%d\n",a,m,b,n,d);
            return;
        }
        c=d,d=r,t=a1,a1=a,a=t-q*a,t=b1,b1=b,b=t-q*b;
    }
}
View Code
相關文章
相關標籤/搜索