扩展欧几里得

解决的问题描述:


对于三个自然数$a,b,c$,求解$ax + by = c$的$(x,y)$的整数解

算法解决:


 首先我们要判断是否存在解,对于这个这个存在整数解的充分条件是$gcd(a,b)$  $|$ $ c$

也就是说$c$为$gcd(a,b)$的一个倍数

然后判定是否有解后,我们需要在这个基础上求一组解(x,y)

由于 $a,b,c$ 都是 $gcd(a,b)$ 的倍数

我们将它们都除以 $gcd(a,b)$ ,不影响后面的计算

这时问题就变成了求对于$ax + by = 1 $ 且 $a,b$ 互质时,$(x,y)$ 的解

对于a,b有负数的情况,我们需要将他们其中一个负数加上另外一个数直到非负。

(由于前面朴素欧几里得定理是不会影响的)

如果a,b是两个负数,直接将整个式子反号,然后放到 c上就行了

下面推一波式子:

  $ax + by = gcd(a,b) = 1$

       $= gcd(b,a$%$b)$(辗转相除)

     $\Rightarrow bx + (a$ % $b)y$(转化一下)

       $= bx + (a - \left \lfloor \frac{a}{b} \right \rfloor b ) y$

       $= bx + ay - \left \lfloor \frac{a}{b} \right \rfloor by$

       $= ay + b( x - \left \lfloor \frac{a}{b} \right \rfloor y )$

 不难发现此时$a$的系数$x$变成了$y$,而$y$变成了$x - \left \lfloor \frac{a}{b} \right \rfloor y$,利用这个性质,我们可以递归求解$(x,y)$

递归的边界其实跟辗转相除一样($b == 0$时退出),此时因为$b = 0$,所以$a = 1,ax + by = 1$,其中的解为$x = 1,y = 0$

作为这些我们就可以在$O(log)$的时间内得到了一组$(x,y)$的特殊解

解系扩展(哈?)


但常常我们要求对于$x or y$ 的最小非负整数解,这个的话我们需要将单个$(x,y)$扩展成了一个解系

如果学过不定方程的话,就可以轻易得到这个解系的,在此不过多赘述了

          

 要记住,(x,y)都要乘上$e$

然后我们直接令$x$为$( x$ % $b ) + b$ % $b$就行了

代码实现


 递归调用的话,$y = x',x = y'$,只需要修改$y$就行了

void Exgcd( int a,int b,int &x,int &y ) { //取地址符即直接改变该元素的数值,可以理解为一个全局变量 
    if( !b ){ //如果b = 0 
        x = 1;
        y = 0;
    }else Exgcd( b,a % b,y,x ), y -= a/b*x;
}

 

posted @ 2022-06-25 11:29  little_sheep_xiaoen  阅读(29)  评论(0编辑  收藏  举报