扩展欧几里得算法、不定方程、同余方程、乘法逆元求解

不定方程理论

设 k ≥ 2,\(c,~ a_1~,...,~a_k\)是整数且\(~ a_1~,...,~a_k\)都不等于零,以及\(~ x_1~,...,~x_k\)是整数变数,则方程

\[~~~a_1x_1 + ...+a_kx_k = c ~~~~~~~~~~~(1) \]

称为 k 元一次不定方程\(~ a_1~,...,~a_k\)称为它的系数

求解方法理论

\({\color{Red}定理一}\):不定方程有解的充分必要条件是它的系数的最大公约数\((a_1,~...~,a_k) | c\)。并且,不定方程(1)有解时,它的解和不定方程

\[\frac{a_1}{g}x_1 +~ ... ~+\frac{a_k}{g}x_k = \frac{c}{g} ~~~~~~(2) \]

的解相同,这里 \(g = (a_1,~...~, a_k)\)

必要性显然。下面来证充分性,若 \(g ~| ~c\),设 \(c= gc_1\),又g = \((a_1,~...~,a_k)\) 必然可以表示为\(a_1,~...~,a_k\)的所有整系数线性组合中最小的正整数,则必有整数 \(y_{1,0},~...~,y_{k,0}\),使得

\[~~a_1y_{1,0} + ~...~ + a_ky_{k,0} = g~~~~~~(3) \]

因此\(x_1 = c_1y_{1,0},~...~,x_k = c_ky_{k,0}\) 即为 (1) 的一组解,这就证明了充分性。由于 (1) 有解时必有 \(g~|~c\),而此时不定方程 (1) 和 (2) 是同一个方程,这就证明了后一结论。

\({\color{Red}定理二}\):设二元一次不定方程

\[~~~~~~~a_1x_1 + a_2x_2 = c~~~~~~~~~~~~~~~~~(4) \]

有解,\(x_{1,0},~x_{2,0}\) 是它的一组解,那么它的所有解为

\[\begin{cases} {x_1 = x_{1,0} + \frac{a_2}{(a_1,a_2)}t}\\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~t = 0, ~±1~,±2,...\\ {x_2 = x_{2,0} - \frac{a_1}{(a_1,a_2)}t}\\ \end{cases} \]

容易直接验证由式 (5) 给出的,对所有整数 t 都满足不等式(4)。反过来,设\(x_1,~x_2\) 是 (4) 的一组解,那么我们有

\[a_1x_1+a_2x_2 = c = a_1x_{1,0} + a_2x_{2,0} \]

进而有

\[a_1(x_1 - x_{1,0}) = - a_2(x_2 - x_{2,0}) \]

\[\frac{a_1}{(a_1,a_2)}(x_1 - x_{1,0}) = -\frac{a_2}{(a_1,a_2)}(x_2 - x_{2,0}) \]

又因为 \((\frac{a_1}{(a_1,a_2))},\frac{a_2}{(a_1,a_2)}) = 1\),则由定理知,

扩展欧几里得算法

求 ax + by = gcd(a, b) 的一组整数解

扩展欧几里得算法:

(1)当 b = 0时,ax + by = a,故 x = 1,b = 0

(2)当 b ≠ 0时,由欧几里得算法,gcd(a, b) = gcd(b, a % b)

由裴蜀定理,得

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

\[~~~~~~~gcd(b, a \% b) = bx_1 + (a \% b)y_1 \]

\[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=bx_1 + (a - {\lfloor\frac{a}{b}\rfloor}×b)y_1 \]

\[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=ay_1 + b(x_1 - \frac{a}{b}y_1) \]

所以 \(x = y_1,~y = x _1 - \frac{a}{c}y_1\)。故可以用递归算法,先求出下一层的\(x_1,~y_1\)。再回代到上一层,层层回代,即可求出特解 \((x_0,~y_0)\)

构造通解

\[\begin{cases} {y = x_{0} + \frac{b}{gcd(a,b)}*t}\\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~t = 0, ~±1~,±2,...\\ {x = y_{0} - \frac{a}{gcd(a,b)}*t}\\ \end{cases} \]

模板: 时间复杂度 :\({\color{Red}O(logn)}\)

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

求解不定方程

求 ax + by = c 的一组整数解

求解步骤:

若 gcd(a, b) | c,则有整数解,先用扩欧算法求 ax + by = gcd(a, b) 的解,再乘以 c / gcd(a, b),即得原方程的特解\(x_0,y_0\)

模板:时间复杂度 :\({\color{Red}O(logn)}\)

int main()
{
    int a, b, c;
    cin >> a >> b >> c;
    int x, y;
    int d = exgcd(a, b, x, y);
    if(c % d == 0) printf("%d %d\n", c/d * x, c/d * y);
    else puts("No solution");
    return 0;
}

求解同余方程

给定整数a,b,m,求解同余方程 ax ≡ b (mod m)。

如果 x 存在整数解,则输出任意一个;

如果不存在,则输出 No solution。

例:8x ≡ 4 (mod 6),整数解 x = 2

求解步骤:

  1. 把同余方程转化成不定方程

    由 ax ≡ b (mod m)

    得 ax = m(-y) + b

    即 ax + my = b

    又有裴蜀定理,当 gcd(a, m) | b时有解

  2. 用扩欧算法,求 ax + my = gcd(a, m)的解,然后把 x 乘以 b / gcd(a, m) 即得原方程的特解。

模板:时间复杂度 :\({\color{Red}O(logn)}\)

int main()
{
    int a, b, m;
    cin >> a >> b >> m;
    int x, y;
    int d = exgcd(a, m, x, y);
    if(b % d == 0) printf("%d\n", 1ll*x * b / d);
    else printf("No solution\n");
    
    return 0;
}

求解乘法逆元

给定整数a,m,且 a 与 m互质时,对于同余方程 ax ≡ 1 (mod m)。求 a 的乘法逆元 x (0 < x < m)

例: 3x ≡ 1 (mod 4),整数解 x = 3

求解步骤:

  1. 乘法逆元转化不定方程,等价变形 ax + my = 1。
  2. 扩欧算法 求 ax + my = gcd(a, m) 的解 x(由于此时 x / gcd(a, m) = x),之后 (x % m + m) % m即为答案。

技巧:“模加模”保证最小正整数

例:x = -7, m = 5,则(-7 % 5 + 5) % 5 = 3

例:x = 7, m = 5,则(7 % 5 + 5) % 5 = 2

模板:时间复杂度 :\({\color{Red}O(logn)}\)

int main()
{
    int a, m;
    cin >> a >> m;
    int x, y;
    int d = exgcd(a, m, x, y);
    if(d == 1) printf("%d\n", (x % m + m) % m); // a, m互质才有逆元
    return 0;
}
posted @ 2023-01-03 16:51  straySheep  阅读(83)  评论(0)    收藏  举报