扩展欧几里得算法是用来求解类似于: ${ax+by=gcd(a,b)}$在${mod~n}$意义下的不定方程的解${x,y}$的算法。
这鬼里鬼气的算法我学了很久,一直都是似懂非懂,只知道写代码而不知道其精髓,在膜拜了网上无数的博客后终于是明白了。
我们用扩展欧几里得算法来计算形如:${ax+by=c}$的不定方程的${x}$和${y}$。
我们都知道可以用欧几里得算法求解${gcd(a,b)}$,也就是${gcd(a,b)=gcd(b,a\%b)}$,而扩展欧几里得算法就是基于它来进行计算的。
我们先考虑如何求解${ax+by=gcd(a,b)}$。$$ax+by=gcd(a,b)=gcd(b,a\% b)$$
$$bx'+(a\% b)y'=gcd(b,a\% b)$$
$$ax+by=bx'+(a\% b)y'$$
$$ax+by=bx'+(a-lfloor a/b floor*b)y'$$
$$ax+by=ay'+b(x'-lfloor a/b floor *y')$$
$$ herefore x=y',y=x'-lfloor a/b floor *y'$$
因为${gcd(a,b)}$在${b=0}$时就会回溯出解,所以我们可以递归求解${ax+by=gcd(a,b)}$,复杂度$lg~n$。
接下来进入正题,如何求解:${ax+by=c}$。$$ax+by=c$$
$$ax'+by'=gcd(a,b)=d$$
我们${ax+by=c}$两边同除${d}$:$$frac{a}{d}x+frac{b}{d}y=frac{c}{d}$$
由于${d=gcd(a,b)}$,所以${a/d}$和${b/d}$都是整数,若${c}$不能整除${d}$的话,那么方程无解。
将2式两边同时乘上${c/d}$,将右侧的${d}$化为${c}$: $$a*frac{c}{d}*x'+b*frac{c}{d}*y'=c$$
于是我们就求出了${x}$和${y}$的一组解(注意这里的${x_0}$和${y_0}$都有可能是$<0$的):$$x_0=frac{c}{d}*x',y_0=frac{c}{d}*y'$$
可是对于一些数论问题,它会要求求出的${x}$的最小的正整数,这怎么办呢。我们先将${x}$和${y}$的解集求出来,还是上面那个式子,两边同时除以${c}$:$$frac{a}{d}*x'+frac{b}{d}*y'=1$$
在这里我们引入一个变量${k}$,原式可以写成:$$(x'+k*frac{b}{d})*frac{a}{d}+(y'-k*frac{a}{d})*frac{b}{d}=1$$
这样做有什么好处呢,其实我们已经可以表示出${x,y}$的通解了,将方程两边同时乘上${c}$:$$x=(x'+k*frac{b}{d})*frac{c}{d},y=(y'-k*frac{a}{d})*frac{c}{d}$$
将${x}$变形一下:
egin{aligned} x&=(x'~mod~frac{b}{d}+frac{b}{d}*lfloorfrac{x'}{b/d} floor+k*frac{b}{d})*frac{c}{d} \ &=lgroup x'~mod~frac{b}{d}+frac{b}{d}*(k+lfloorfrac{x'}{b/d} floor) group*frac{c}{d} end{aligned}
因为${b/d}$为正数,所以里面的值随着${k}$的增大而增大,所以我们不妨令:$$k=-lfloor frac{x'}{b/d} floor$$
这样一来,求出来的${x}$就是最小正整数了:$$x=(x'~mod~frac{b}{d})*frac{c}{d}$$
因为${x’}$求出来可能是负的所以最后还要做点处理,${x}$最后的的表达式:$$x=(x'*frac{c}{d}\%frac{b}{d}+frac{b}{d})\%frac{b}{d}$$