歐幾里德算法 || 擴展歐幾里德算法


參考文獻:1. http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

                   2 . https://www.cnblogs.com/hadilo/p/5914302.html

一、歐幾里得算法(重點是證明,對后續知識有用)

  歐幾里得算法,也叫輾轉相除,簡稱 gcd,用於計算兩個整數的最大公約數

  定義 gcd(a,b) 為整數 a 與 b 的最大公約數

  引理:gcd(a,b)=gcd(b,a%b)

  證明:

    設 r=a%b , c=gcd(a,b)

    則 a=xc , b=yc , 其中x , y互質

    r=a%b=a-pb=xc-pyc=(x-py)c

    而b=yc

    可知:y 與 x-py 互質

    證明:

                假設 y 與 x-py 不互質

                設 y=nk , x-py=mk , 且 k>1 (因為互質)

                將 y 帶入可得

                x-pnk=mk

                x=(pn+m)k

                則 a=xc=(pn+m)kc , b=yc=nkc

                那么此時 a 與 b 的最大公約數為 kc 不為 k

                與原命題矛盾,則 y 與 x-py 互質

    因為 y 與 x-py 互質,所以 r 與 b 的最大公約數為 c

    即 gcd(b,r)=c=gcd(a,b)

    得證

  當a%b=0時,gcd(a,b)=b

 遞歸算法:

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

優化:

int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}
View Code

二、擴展歐幾里得算法

   擴展歐幾里得算法,簡稱 exgcd,一般用來求解不定方程,求解線性同余方程,求解模的逆元等

  引理:存在 x , y 使得 gcd(a,b)=ax+by

  證明:

         當 b=0 時,gcd(a,b)=a,此時 x=1 , y=0

         當 b!=0 時,

         設 ax1+by1=gcd(a,b)=gcd(b,a%b)=bx2+(a%b)y2

         又因 a%b=a-a/b*b

         則 ax1+by1=bx2+(a-a/b*b)y2

    ax1+by1=bx2+ay2-a/b*by2

    ax1+by1=ay2+bx2-b*a/b*y2

    ax1+by1=ay2+b(x2-a/b*y2)

    解得 x1=y2 , y1=x2-a/b*y2

    因為當 b=0 時存在 x , y 為最后一組解

    而每一組的解可根據后一組得到

    所以第一組的解 x , y 必然存在

    得證

  根據上面的證明,在實現的時候采用遞歸做法

  先遞歸進入下一層,等到到達最后一層即 b=0 時就返回x=1 , y=0

  再根據 x=y’ , y=x’-a/b/y’ ( x’ 與 y’ 為下一層的 x 與 y ) 得到當層的解

  不斷算出當層的解並返回,最終返回至第一層,得到原解

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;
}
View Code

擴展歐幾里德算法的應用主要有以下三方面:

(1)求解不定方程;

(2)求解模線性方程(線性同余方程);

(3)求解模的逆元;

( 1 )exgcd 解不定方程(使用不將a與b轉為互質的方法)

  對於 ax+by=c 的不定方程,設 r=gcd(a,b)

  當 c%r!=0 時無整數解

  當 c%r=0 時,將方程右邊 *r/c 后轉換為 ax+by=r 的形式

  可以根據擴展歐幾里得算法求得一組整數解 x0 , y0

  而這只是轉換后的方程的解,原方程的一組解應再 *c/r 轉變回去

  (如 2x+4y=4 轉換為 2x+4y=2 后應再將解得的 x , y 乘上2)

  則原方程解為 x1=x0*c/r , y1=x0*c/r

  通解 x=x1+b/r*t , y=y1-a/r*t ,其中 t 為整數

  證明:

    將 x , y 帶入方程得

    ax+ab/r*t+by-ab/r*t=c

    ax+by=c

    此等式恆成立

    得證

  這里 b/r 與 a/r 為最小的系數,所以求得的解是最多最全面的

  證明:

    為了推出證明中的 ax+by=c ,且想達到更小的系數,只能將 b/r 與 a/r 同除以一個數 s

    而 b/r 與 a/r 互質,且 s 為整數,則 s=1 ,不影響通解

    那么 b/r 與 a/r 就為最小的系數

    得證

bool linear_equation(int a,int b,int c,int &x,int &y)
{
    int d=exgcd(a,b,x,y);
    if(c%d)
        return false;
    int k=c/d;
    x*=k; y*=k;    //求得的只是其中一組解
    return true;
}
View Code

   附加一道題的代碼:

 #include<stdio.h>
 int a,b,c,x,y;
 int exgcd(int a,int b,int &x,int &y)
 {
     if(!b)
     {
         x=1;
         y=0;
         return a;
     }
     int e=exgcd(b,a%b,x,y);
     int temp=x;
     x=y;
     y=temp-a/b*y;
     return e;
 }
 int main()
 {
     scanf("%d%d%d",&a,&b,&c);
     int k=exgcd(a,b,x,y);
     if(c%k)
        printf("Impossible\n");
     else
     {
         k=c/k;
         x*=k;
         y*=k;
         printf("x=%d,y=%d\n",x,y);
     }
     return 0;
 }
View Code

 

 解出來的解后可以轉化為最小整數解:

x=(x%b+b)%b;(求出的就是最小正整數解);

套用exgcd模板求得的是一組特殊解,但其實這一個方程式是有一個解系,在很多問題中是要你求得最小整數解,下面我們就解決這個問題,在閱讀過很多博客加上自己的理解總結了兩種方法(其實差距不大)

1、a*x+b*y=gcd(a,b)

void exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return; } int x1,y1; exgcd(b,a%b,x1,y1); x=y1; y=x1-(a/b)*y1; }
x=(x%b+b)%b;(求出的就是最小正整數解)
2.可以說這是求最小正整數的模板
LL e_gcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    LL ans=e_gcd(b,a%b,x,y);
    LL temp=x;
    x=y;
    y=temp-a/b*y;
    return ans;
}

LL cal(LL a,LL b,LL c)
{
    LL x,y;
    LL gcd=e_gcd(a,b,x,y);
    if(c%gcd!=0) return -1;
   LL b_=b/gcd;
   x=(x*(c/gcd)%b_)%b_+b_)%b_;
   return x;
}
View Code

 

這兩種本質上沒啥區別,只是在一些問題中a,b等系數可能為負,第一種需要預處理,而第二種則可以直接用
附上學習代碼處:https://blog.csdn.net/tianyuhang123/article/details/52102686

 

還會往下拓展。。。。盡情期待!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM