扩展欧几里得算法
1.欧几里得算法
欧几里得算法是一种用来求两个数的最大公因数的算法。用欧几里得算法求 \((a, b)\) 时,主要步骤如下:
1.如果 \(a \mod b = 0\),则 \((a, b) = b\);
2.如果 \(a \mod b \ne 0\),则求出 \((b, a \mod b)\) 的值
3.\((a, b)\) 的值就是 \((b, a \mod b)\) 的值。
递归处理即可。代码实现如下:
int Gcd(int a, int b)
{
if (a % b == 0) return b;
return Gcd(b, a % b);
}
当然,也可以直接使用C++里自带的函数 __gcd 直接计算。
2.扩展欧几里得算法
扩展欧几里得算法是用来解不定方程的算法。这种算法和欧几里得算法一致。
不定方程的定义:没有一定的解的方程。如:方程 \(x + y = 2\),如果其他条件,这个方程就是不定方程。在现阶段,我们一般只研究不定方程的整数解。
不定方程解的情况:一个不定方程 \(ax + by = c\),若 \(c\) 为 \((a, b)\) 的倍数,则方程有整数解,否则没有。这里就不给出证明了,因为我不会。
如果现在有一个方程 \(ax + by = (a, b)\),我们可以模仿欧几里得算法的步骤:
1.若 \(b = 0\),则 \(x = 1, y\) 为任意数。为了方便,这里把 \(y\) 设成 \(0\)。
2.若 \(a \ne 1\) 或 \(b \ne 0\),则求出方程 \(bx + (a \mod b)y = (b, a \mod b)\) 的解。根据欧几里得算法,\((b, a \mod b) = (a, b)\),所以方程 \(bx + (a \mod b)y = (b, a \mod b)\) 的解就是方程 \(bx + (a \mod b)y = (a, b)\) 的解。
3.根据方程 \(bx + (a \mod b)y = (a, b)\) 解的情况,求出原方程解的情况。
那根据方程方程 \(bx + (a \mod b)y = (a, b)\) 的解,\(ax + by = (a, b)\) 解的情况怎么求呢?不妨设方程 \(bx + (a \mod b)y = (a, b)\) 的一个解为 \(x = x_0, y = y_0\),则有 \(bx_0 + (a \mod b)y_0 = (a, b)\),然后把 mod 换成它减去向下取整的形式,则 \(bx_0 + (a - \lfloor \frac{a}{b} \rfloor \times b)y_0 = (a, b)\),整理一下左式得 \(ay_0 + b(x_0 - \lfloor \frac{a}{b} \rfloor y_0) = (a, b)\),因此,我们可以得到原方程的解为 \(x = y_0, y = x_0 - \lfloor \frac{a}{b} \rfloor\)。
因此,代码就容易了。代码如下:
pair <int, int> exgcd(int a, int b)
{
if (b == 0) return {1, 0};
pair <int, int> p = exgcd(b, a % b);
return {p.second, p.first - a / b * p.second};
}
3.乘法逆元
乘法逆元的定义:\(a\) 在模 \(b\) 意义下,使得 \(ax\) 与 \(1\) 同余的 \(x\) 的整数。比如 \(3\) 在模 \(10\) 下的最小的正整数逆元为 \(7\)。
乘法逆元的求法:若要求 \(a\) 在模 \(b\) 意义下的逆元,我们设这个逆元为 \(x\),则 \(ax \equiv 1 \pmod m\),我们设 \(ax = m \times (-y) + 1\),则 \(ax + my = 1\)。因为逆元是整数,所以有逆元的要求就是 \(a \perp b\),因此,我们求逆元的时候,先判断两个数是否互质,再用扩展欧几里得算法来求逆元的值。因为逆元在方程中为 \(x\),所以逆元就是解中的第一个数。当然,一般情况下,我们求的是逆元中最小的正整数,我们不仅要保证它是正整数,还要保证它最小,所以我们需要把它先对 \(m\) 取模后的结果加上 \(m\) 再模 \(m\)。代码:
pair <int, int> exgcd(int a, int b)
{
if (b == 0) return {1, 0};
pair <int, int> p = exgcd(b, a % b);
return {p.second, p.first - a / b * p.second};
}
int inverse_element(int a, int m)
{
pair <int, int> p = exgcd(a, m);
return (p.first % m + m) % m;
}

浙公网安备 33010602011771号