有这样的问题:
给你两个整数数$(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} floor imes b) imes y'$
$=bx'+ay'-lfloor frac{a}{b} floor imes b imes y'$
$=ay'+b(x'-lfloor frac{a}{b} floor y')$
不难发现,$x=y'$,$y=(x'-lfloor frac{a}{b} floor 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$
$axequiv 1(mod b)$
当模数不是质数的时候你就会知道这东西有多重要。