扩展欧几里得算法

费马定理(Fermat’s theorem)使我们能够通过二进制指数法(binary exponentiation)在O(log⁡n)O(\log n)的操作内计算模数除法的乘法逆元(modular multiplicative inverses),但这只适用于对质数取模。它的一个推广是欧拉定理(Euler’s theorem),此定理表明,如果 m 和 a 互质(即他们之间除了1,没有其他公约数),那么

aϕ(m)≡1(mod  m)a^{\phi(m)} ≡ 1(\mod m)

其中,ϕ(m)\phi(m)是欧拉函数,定义为小于mm的正整数xx与mm互质的个数。当mm是一个质数时,所有小于mm的m−1m-1个正整数与mm都是互质的,所以ϕ(m)=m−1\phi(m)=m-1,这就得出了费马定理。

这允许我们通过ϕ(m)\phi (m)来计算aa的模除乘法逆元,记作aϕ(m)−1a^{\phi (m)−1},但反过来,计算ϕ(m)\phi (m)并不那么快速:通常你需要获得mm的因数分解才能做到这一点。有一种更通用的方法,它是通过修改欧几里得算法(Euclidean algorthm)实现的。

算法

扩展欧几里得算法(Extended Euclidean algorithm),除了用来寻找最大公约数g=gcd⁡(a,b)g = \gcd (a,b),也可以用来寻找整数xx和yy满足:

a⋅x+b⋅y=ga \cdot x + b \cdot y = g

这可以通过将bb替换为mm和gg替换为11来解决了寻找模运算逆元的问题:

a−1⋅a+k⋅m=1a^{−1}⋅a+k⋅m=1

如果aa和mm不是互质的,那么就没有解,因为aa和mm的任何整数组合都不能得到一个不是他们最大公约数的倍数的数。

算法同样是递归的:它先计算出gcd⁡(b,amod  b)\gcd (b,a \mod b)的系数x′x'和y′y',然后恢复初始数字对的解。如果我们有一对(b,amod  b)(b,a \mod b)的解(x′,y′)(x',y'):

b⋅x′+(amod  b)⋅y′=gb⋅x′+(a \mod b)⋅y′=g

那么,为了得到初始输入的解,我们可以将表达式(amod  b)(a \mod b)重写为(a−⌊ba⌋⋅b)(a−⌊\frac{b}{a}⌋⋅b)并将它代入前述方程:

b⋅x′+(a−⌊ba⌋⋅b)⋅y′=gb⋅x′+(a−⌊\frac{b}{a}⌋⋅b)⋅y′=g

现在我们按aa和bb进行分组,重新排列表达式可以得到:

a⋅y′⏟x+b⋅(x′−⌊ba⌋⋅y′)⏟y=ga \cdot \underbrace{y'}_x + b \cdot \underbrace{(x' - ⌊\frac{b}{a}⌋ \cdot y')}_y = g

将上式与初始表达式相比较,可以得出aa和bb的系数即为初始的xx和yy。

实现

我们将算法实现为递归函数。由于它的输出不是一个而是三个整数,我们通过引用将系数传递给它:

int gcd(int a, int b, int &x, int &y) {
if (a == 0) {
x = 0;
y = 1;
return b;
}
int x1, y1;
int d = gcd(b % a, a, x1, y1);
x = y1 - (b / a) * x1;
y = x1;
return d;
}

为了计算模运算的乘法逆元,我们只需传递aa和mm,然后返回算法找到的xx系数。由于我们传递了两个正数,其中一个系数将是正的,另一个系数将是负的(具体哪一个取决于迭代次数是奇数还是偶数),所以我们需要检查xx是否为负,并加上mm以获得正确的余数。

int inverse(int a) {
int x, y;
gcd(a, M, x, y);
if (x < 0)
x += M;
return x;
}

这段代码的执行时间约为160ns,比用二进制指数法求逆元快10ns。为了进一步优化它,我们同样可以用迭代方式实现,这样的执行时间为135ns:

int inverse(int a) {
int b = M, x = 1, y = 0;
while (a != 1) {
y -= b / a * x;
b %= a;
swap(a, b);
swap(x, y);
}
return x < 0 ? x + M : x;
}

需要注意的是,和二进制指数法不同,执行时间取决于aa的值。例如,对于特定的mm值(109+7)(10^9+7),性能表现最差的输入值为564400443564400443,这种情况下,算法执行37次迭代,花费250ns。

练习:可以尝试将相同的技术应用于二进制GCD(不过,除非你在优化方面比我强,否则这不会获得性能上的提升)。