1. 程式人生 > >擴展歐幾裏得求解的個數

擴展歐幾裏得求解的個數

https href 擴展 ret inline 計數 化簡 求解 tails

知識儲備

擴展歐幾裏得定理
歐幾裏得定理
(未掌握的話請移步擴展歐幾裏得)

正題

設存在\(ax+by=gcd(a,b)\),求x,y。
我們已經知道了用擴歐求解的方法是遞歸,終止條件是x==1,y==0;

int exgcd( int a, int b, int &x, int &y ) {
    if( b == 0 ) {
        x = 1;
        y = 0;
        return a;
    }
    int tmp = a % b;
    if( tmp > b ) swap( tmp, b );
    int ans=exgcd(b,a%b,x,y);
    tmp = x;
    x = y;
    y = tmp - a / b * y;
    return ans;
}

到b==0時,我們可以得到一組解:(1,0)。
接下來再逐步回帶,求出所有可能的解。具體是為什麽呢?

證明

已知:

  • \(ax1+by1=gcd(a,b)\)
  • \(bx2+(a mod b)y2=gcd(a,b)\)
  • \(a mod b = a-a/b*b\)

可求得:
\(ax1+by1=bx2+(a mod b)y2=gcd(a,b)\)

\(ax1+by1=bx2+(a-a/b*b)y2=gcd(a,b)\)
化簡得
\(ax1+by1=bx2+ay2-a/b*b*y2=gcd(a,b)\)
所以可證出:
對於每一次遞歸中的x1y1,與上一次遞歸中的x2y2存在如下關系:
\(x1 = y2\)

\(y1 = x2 - a / b * y2\)

證明畢,
每次的x和y均存在遞歸關系,所以我們可以在求得一組解後回溯時回帶求出其他解,此時計數即可。

P.S.

對於求方程正整數解的個數的題,需要註意特判
設ax+by=c,給定a,b,c,求x,y的正整數解個數

  • x=0,y=0,z=0時,方程無數解
  • x=0,y=0,z!=0時,方程無解
  • x,y<0,z>0時方程無解,反之亦然

擴展歐幾裏得求解的個數