最大公約數


 

一、輾轉相除法

  

inline int GCD(int x,int y)
{
    int r=x%y;
    while(r) x=y,y=r,r=x%y;
    return y;
}

  原理證明

  • 因為a=b+c,於是b,c的公約數也必然是a的約數,假設(b,c)=e,
  • ((b,c)=e表示e為b和c的最大公約數)那么有elb+c,即ela,
  • 根據"d是b,c的公約數"知道dle,,
  • 又因為e也是a,b的公約數,eld,綜上有e=d
  • 可見(a,b)=(b,c)=d

 

二、二進制算法

可將x,y分為六種情況進行討論:

  1. 若x=0或y=0:返回y或x;
  2. 若x<y:交換x,y;
  3. 若x為偶數且y為偶數:gcd(x/2,y/2);
  4. 若x為偶數且y為奇數:gcd(x/2,y);
  5. 若x為奇數且y為偶數:gcd(x,y/2);
  6. 若x為奇數且y為奇數:gcd(x-y,y);
inline int gcd(int x,int y)
{
    int n=0,m=0;
    while(!(x&1)) ++n,x>>=1;
    while(!(y&1)) ++m,y>>=1;
    n=min(n,m);
    while(1)
    {
         if(x<y) swap(x,y);
         if(!(x-=y)) return y<<n;
         while(!(x&1)) x>>=1;
    }
} 

 

三、最小公倍數

  幾個數的最小公倍數為幾個數的乘積除以這幾個數的最大公約數

四、擴展歐幾里得

  擴展歐幾里德算法是用來在已知a, b求解一組x,y,使它們滿足貝祖等式(裴蜀定理,博客整除這一章有介紹): ax+by = gcd(a, b) =d(解一定存在,根據數論中的相關定理)。擴展歐幾里德常用在求解模線性方程及方程組中。

  公式表述1

  • gcd(a,b)=gcd(b,a mod b)
  • 證明:a可以表示成a = kb + r,則r = a mod b
  • 假設d是a,b的一個公約數,則有
  • d|a, d|b,而r = a - kb,因此d|r
  • 因此d是(b,a mod b)的公約數
  • 假設d 是(b,a mod b)的公約數,則
  • d | b , d |r ,但是a = kb +r
  • 因此d也是(a,b)的公約數
  • 因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等,得證

  公式表述2

  • 首先根據裴蜀定理得,解一定存在
  • 其次因為gcd(a,b)=gcd(b,a%b),所以p*a+q*b=gcd(b,a%b)=p*b+q*a%b=p*b+q*(a-a/b*b)=q*a+(p-a/b*q)*b,這樣它就把a與b的線性組合簡化為b與a%b的線性組合了
  • 假根據前面的結論,a,b都在減小,當b減小到0時,得出p=1,其遞歸會最初的p,q就行了
//其中x,y為滿足x*a+y*b=gcd(a,b)的解,ret為gcd(a,b);
int exgcd(int a,int b,int &x,int &y)
{
    int ret,temp;
    if(!b) 
    {
        x=1,y=0;
        return a;
    }
    ret=exgcd(b,a%b,x,y);
    temp=x,x=y,y=temp-a/b*y;
    return ret;
}

 

五、求解線性方程

  定理一:對於方程a*x+b*y=c,該方程等價於a*x≡c(mod) b,有整數解的充分必要條件是:c%GCD(a,b)=0。

  定理二:若GCD(a,b)=1,且x0,y0為a*x+b*y=c的一組解,則方程的任意解可以表達為  x=x0+b*t,y=y0-a*t,對於任意整數t皆成立

  根據定理一,我們可以求出方程a*x0+b*y0=gcd(a,b)的一組解,x0,y0,兩邊同時除以GCD(a,b)再乘以c就得到原方程的一個解

  根據定理二,我們就可以求出一組特解(最小整數解),t=b/gcd(a,b),x=(x%t+t)%t;

  

 

 

 

 


免責聲明!

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



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