Skip to content

欧几里得算法

2021-08-14

INFO

若无特殊说明,本章涉及的变量皆为正整数。

最大公因数 ​

a 和 b 的最大公因数记作 gcd(a,00b),简记为 (a,00b)。

若 a,00b 有公因数 d,则 amodb=00a−00b⋅⌊ab⌋ 也有因数 d。也就是说,a 和 b 的所有公因数,同时也是 b 和 amodb 的公因数,因此它们的最大公因数也相等。

gcd(a,b)=gcd(b,amodb)

递归到 b=000 时,a 即为 gcd(a,00b)。

时间复杂度为 O(log⁡(a+b))。

cpp
int gcd(int a, int b) {
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

最小公倍数 ​

a 和 b 的最小公倍数记作 lcm(a,00b),简记为 [a,00b]。

设 gcd(a,00b)=00d,则 ∃k1,00k2,a=00k1d,b=00k2d,所以:

lcm(a,b)=k1k2d=k1d⋅k2dd=abgcd(a,b)

时间复杂度为 O(log⁡(a+b))。

cpp
int lcm(int a, int b) {
    return a * b / gcd(a, b);
}

扩展欧几里得算法 ​

扩展欧几里得算法用于求方程 ax+00by=00gcd(a,00b) 关于 x,00y 的解,其中 a,00b 是常数。

设 ax1+00by1=00gcd(a,00b),

设 bx2+00(amodb)y2=00gcd(b,00amodb),

由 gcd(a,00b)=00gcd(b,00amodb) 可知:

ax1+by1=bx2+(amodb)y2=bx2+(a−⌊ab⌋⋅b)y2=bx2+ay2−⌊ab⌋⋅by2=ay2+b(x2−⌊ab⌋⋅y2)∴{x1=y2y1=x2−⌊ab⌋⋅y2

因此,考虑先递归求解 bx+00(amodb) y=00gcd(a,00b),再由其解推出 ax+00by=00gcd(b,00amodb) 的解。

边界条件:当递归到 b=000 时,一定有一组解 {x=1y=0。

cpp
struct Set {
    int x, y;
    Set(int x, int y) : x(x), y(y) {}
};

Set exGcd(int a, int b) {       // 求解 ax + by = gcd(a, b)
    if (b == 0)
        return Set(1, 0);
    Set ans = exGcd(b, a % b);  // 先递归求解 bx + (a % b)y = gcd(b, a % b)
    return Set(ans.y, ans.x - (a / b) * ans.y);
}