扩展欧几里得算法学习笔记
扩展欧几里得算法是用来求解类似于: ${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 \rfloor*b)y'$$
$$ax+by=ay'+b(x'-\lfloor a/b \rfloor *y')$$
$$\therefore x=y',y=x'-\lfloor a/b \rfloor *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}$变形一下:
\begin{aligned} x&=(x'~mod~\frac{b}{d}+\frac{b}{d}*\lfloor\frac{x'}{b/d}\rfloor+k*\frac{b}{d})*\frac{c}{d} \\ &=\lgroup x'~mod~\frac{b}{d}+\frac{b}{d}*(k+\lfloor\frac{x'}{b/d}\rfloor)\rgroup*\frac{c}{d} \end{aligned}
因为${b/d}$为正数,所以里面的值随着${k}$的增大而增大,所以我们不妨令:$$k=-\lfloor \frac{x'}{b/d} \rfloor$$
这样一来,求出来的${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}$$