欧几里得算法&扩展欧几里得算法

创建时间:2025-05-20


欧几里得算法

其实欧几里得算法就是我们常说的辗转相除法,即通过递归式

\[\gcd(a,b)=\begin{cases} a, & b = 0 \\ \gcd(b,a \bmod b), & b \neq 0 \\ \end{cases}\]

求出 \(a\)\(b\) 的最大公因数。

考虑如何证明 \(gcd(a,b)=\gcd(b,a \bmod b),b \neq 0\)

\(a<b\) 时,有 \(a \bmod b = a\),所以 \(\gcd(b, a\bmod b)=gcd(b,a)\),又因为 \(\gcd(a,b)=\gcd(b,a)\),所以 \(\gcd(a,b)=\gcd(b,a \bmod b)\)

\(a \ge b\) 时,令 \(a=qb+r(q \in \N^*,r \in \N,r<b)\),则对于 \(a、b\) 的任意一个因数 \(d\) 都有 \(d \mid a=(qb+r)\),于是 \(d\mid r\),所以 \(d\)\(b\)\(r\) 的公因数。对于任意 \(b\)\(r\) 的公因数 \(d'\),有 \(d' \mid qb,d'\mid r\),所以 \(d'\mid (qb+r)=a\),所以 \(d'\)\(a\)\(b\) 的公因数。故 \(a\)\(b\) 的公因数集合等于 \(b\)\(r\) 的公因数集合,所以 \(a\)\(b\) 的最大公因数也等于 \(b\)\(r\) 的最大公因数,即 \(\gcd(a,b)=\gcd(b,r)=\gcd(b,a \bmod b)\)

综上所述,\(\gcd(a,b)=\gcd(b,a \bmod b),b \neq 0\) 得证。

代码:

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

注:有时在写题时会偷懒直接调用C++中的 __gcd(a,b),这就是对上述代码的一个封装,只是比赛时禁止使用 __ 开头的函数/类模板。

扩展欧几里得算法

扩展欧几里得算法的可以在求出 \(\gcd(a, b)\) 的同时得到二元一次不定方程 \(ax + by = \gcd(a, b)\) 的一组解。

先观察下列两个方程(\(b \neq 0\)):

\[ax+by=\gcd(a,b) \]

\[bx_0+(a \bmod b)y_0=\gcd(b,a \bmod b) \]

由欧几里得算法我们可以知道 \(\gcd(a,b)=\gcd(b,a \bmod b)\),所以可以将二式改写为:

\[ax+by=d \]

\[bx_0+(a \bmod b)y_0=d \]

又因为 \(a \bmod b=a-\lfloor \frac a b \rfloor\),于是

\[bx_0+(a - \lfloor \frac a b \rfloor)y_0=d \]

整理得:

\[ay_0+b(x_0-\lfloor \frac a b \rfloor y_0)=d \]

此时若我们已知 \(x_0\)\(y_0\) 的一组解,就能令 \(x=y_0,y=x_0-\lfloor \frac a b \rfloor y_0\) 得到 \(x\)\(y\) 的一组解。故只需要递归,就能求出 \(ax+by=d(b \neq 0)\) 的解。又因为当 \(b=0\) 时原方程转变为 \(ax=\gcd(a,0)=a\),此时只需令 \(a=1,b=0\)\(b\) 也可以取其它任意值)即可。

int exgcd(int a, int b, int& x, int& y) {
    if (b == 0) {
        x = 1, y = 0;
        return a;
    }
    int x0, y0, d = exgcd(b, a % b, x0, y0);
    x = y0, y = x0 - a / b * y0;
    return d;
}

有时也写成:

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

扩展欧几里得的应用

用扩展欧几里得,我们可以求出 \(ax+by=gcd(a,b)\) 的一组解,由于C++负数取模的特性和不定方程的周期性,令 \(x \leftarrow (x \cdot \frac c d \bmod \frac b d+\frac b d) \bmod \frac b d,d=gcd(a,b)\) 可得 \(ax + by = c\) 的最小非负整数解,这是扩展欧几里得的最常见的用处。

注意在扩展欧几里得后一定要特判 \(d \mid c\) 是否成立!!!

注意该式中的 \(c\)\(d\) 的一定要除以 \(d\),否则会使答案偏大!!!

其它例题:
P1516 青蛙的约会(扩展欧几里得模板题)
P5656 【模板】二元一次不定方程 (exgcd)(强数据扩展欧几里得模板)
P2421 [NOI2002] 荒岛野人(枚举+扩展欧几里得)

posted @ 2026-05-19 12:32  xubaichuan  阅读(13)  评论(0)    收藏  举报