【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元

有这样的问题:

给你两个整数数$(a,b)$,问你整数$x$和$y$分别取多少时,有$ax+by=gcd(x,y)$,其中$gcd(x,y)$表示$x$和$y$的最大公约数。

数据范围$a,b≤10^{18}$。

求解这个问题有一种方法,叫做扩展欧几里得算法(简称扩欧),其本质是一个递归求解的过程。

首先由一个前置的结论是$gcd(x,y)=gcd(y,x\%y)$。此处的$\%$为$c++$中取模操作,下同。

 

我们不妨设$a>b$

当$a≠0,b=0$时,则显然有$x=1,y=0$。此时$gcd(a,b)=a$。

当$b≠0$时,我们假设我们已经求出了$bx'+(b\%a)y'=gcd(a,b)$的$x'$和$y'$(这是式1),我们现在要求的是$ax+by=gcd(a,b)$。

我们对式子$1$做一些微小的变式

原式$=bx'+(b\%a)y'$

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

$=bx'+ay'-\lfloor \frac{a}{b} \rfloor \times b\times y'$

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

不难发现,$x=y'$,$y=(x'-\lfloor \frac{a}{b}\rfloor y')$就是一组符合条件的解。

然后无脑递归解决即可,代码很短,复杂度显然是$O(\log_2 a)$的。

1 void exgcd(int a,int b,int &x,int &y){
2     if(!b) {x=1; y=0; return;}
3     exgcd(b,a%b,y,x);
4     y-=a/b*x;
5 }

 

下面来说下这东西能干啥

我们不难发现,我们需要求$a$在模$b$意义下的乘法逆元(前提条件,$a$与$b$互质)

我们可以执行一次$exgcd(a,b,x,y)$,然后$x$就是$a$在模$b$意义下的逆元。

证明显然:

$ax+by=1$

$ax\equiv 1(\mod b)$

当模数不是质数的时候你就会知道这东西有多重要。

 

posted @ 2019-03-25 22:05  AlphaInf  阅读(321)  评论(0编辑  收藏  举报