2018/6/8 星期五

如何理解扩展欧几里得算法中解系的最小间距.

今天跟乐乐讲解扩展欧几里得算法的时候,突然明白了解系的最小间距是怎么得来的, 下面写一下推导过程.

//求出ax+by=gcd(a,b)的一组解
int ext_gcd(int a,int b, int &x ,int &y)
{
    if(b == 0)
    {
        x=1; y=0;
        return a;
    }
    int c = ext_gcd(a, b, x, y);
    int xt = x;
    x = y;
    y = xt - a / b * y;
    return c;
}

通常要求的是 ax+by=nax+by=n的一组解,设c=gcd(a,b), 我们一般会先通过ext_gcd()函数求出
ax+by=cax+by=c的一组解(x0,y0)(x_0,y_0)使得ax0+by0=cax_0+by_0=c, 然后判断n是否能被c整除, 如果不可以
整除,则原方程无解. 否则, 令k=n/ck=n/c,则akx0+bky0=kc=na\cdot kx_0 + b\cdot ky_0=kc=n,此时(kx0,ky0)(kx_0,ky_0)
即为原方程的解, 实际上, 从(x0,y0)(x_0,y_0)我们扩展出了解系:
X=x0+T1t=x0+b/gcd(a,b)tX = x_0 + T_1 \cdot t = x_0 + b/gcd(a,b) \cdot t
Y=y0T2t=y0a/gcd(a,b)tY = y_0 - T_2 \cdot t = y_0 - a/gcd(a,b) \cdot t

tt取任意整数,都可以得到一组解(Xi,Yi)(X_i,Y_i)满足aXi+bYi=naX_i+bY_i=n成立. 下面证明为什么
T1=b/gcd(a,b)T_1 = b/gcd(a,b)
T2=a/gcd(a,b)T_2 = a/gcd(a,b)
(因为a,b,gcd(a,b)都是正整数, 所以T1,T2T_1,T_2也都是正整数)

(X,Y)(X,Y)代入原方程得: aX+bY=naX+bY=n
a(x0+T1t)+b(y0T2t)=n\Rightarrow a(x_0+T_1\cdot t) + b(y_0-T_2\cdot t)=n
ax0+by0+(aT1bT2)t=n\Rightarrow ax_0 + by_0 + (aT_1-bT_2)\cdot t = n
ax0+by0=n,(aT1bT2)t=0\because ax_0+by_0=n, \therefore (aT_1-bT_2)\cdot t = 0
t̸=0t\not=0时, 有aT1bT2=0aT_1-bT_2=0,即aT1=bT2aT_1=bT_2, 我们要求最小的T1,T2T_1,T_2
T=aT1=bT2T=aT_1=bT_2, 显然当TT最小的时候, T1,T2T_1,T_2也最小, 那么TT最小为多少呢,
因为TT既是a的倍数, 也是b的倍数, 所以TT是a和b的公倍数, 所以当TT为a和b的最小
公倍数时,即T=ab/gcd(a,b)T=ab/gcd(a,b)时,T1,T2T_1,T_2最小,此时有:
aT1=ab/gcd(a,b)T1=b/gcd(a,b)aT_1=ab/gcd(a,b) \Rightarrow T_1=b/gcd(a,b)
bT2=ab/gcd(a,b)T2=a/gcd(a,b)bT_2=ab/gcd(a,b) \Rightarrow T_2=a/gcd(a,b)
证毕.

下面用一个实例演示一下: 3x+4y=13x + 4y=1
显然(x0,y0)=(1,1)(x_0,y_0)=(-1,1)是原方程的一组解(31+41=13\cdot-1 + 4\cdot 1 = 1),
T1=b/gcd(a,b)=4/1=4T_1 = b/gcd(a,b)=4/1 = 4
T2=a/gcd(a,b)=3/1=3T_2 = a/gcd(a,b)=3/1 = 3
t=1t=1,得:
x1=x0+T11=1+4=3x_1 = x_0 + T_1\cdot1 = -1 + 4 = 3
y1=y0T21=13=2y_1 = y_0 - T_2\cdot1 = 1 - 3 = -2
x1+4y1=33+4(2)=1\Rightarrow x_1 + 4y_1 = 3\cdot3 + 4\cdot(-2) = 1

t=2t=2,得:
x2=x0+T12=1+42=7x_2 = x_0 + T_1*2=-1+4*2= 7
y2=y0T22=132=5y_2 = y_0 - T_2*2=1-3*2=-5
3x2+4y2=3745=1;\Rightarrow 3x_2+4y_2=3*7-4*5=1;