【数学】扩展欧几里得算法

二元一次不定方程

扩展欧几里得算法,简称 扩欧\(\rm exgcd\)),是用来求出方程

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

的整数解的,其中 \(a,b\) 均为整数.

前置芝士:欧几里德算法裴蜀定理

我们考虑欧几里德算法的最后一步,当 \(b=0\) 时,要使得

\[ax+0y=\gcd(a,0)=a \]

成立,那么只要取 \(x=1\)\(y\) 取任意整数即可,不妨取 \(y=0\).

因为 \(\gcd(a,b)=\gcd(b,a\bmod b)\),所以可以考虑当整数 \(x,y\) 使得

\[bx+(a\bmod b)y=\gcd(b,a\bmod b) \]

成立时,如何推出使得

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

成立的 \(x',y'\).

对于 \(bx+(a\bmod b)y=\gcd(b,a\bmod b)\)

\(\begin{aligned}等式左边&=bx+(a-b\left\lfloor\frac{a}{b}\right\rfloor)y\\&=ay+b(x-\left\lfloor\frac{a}{b}\right\rfloor y)\end{aligned}\)

\(\begin{aligned}等式右边&=\gcd(a,b)\end{aligned}\)

所以要使 \(ax'+by'=\gcd(a,b)\) 的话,取 \(x'=y,y'=x-\left\lfloor\frac{a}{b}\right\rfloor y\) 即可.

就这样一直递归.

下面提供了求解 \(ax+by=\gcd(a,b)\) 的同时返回 \(\gcd(a,b)\) 的代码.

int x, y;

int exgcd(int a, int b)
{
	if (!b)
	{
		x = 1, y = 0;
		return a;
	}
	int Gcd = exgcd(b, a % b);
	int tmp = x; // x 会被覆盖掉,先存下来
	x = y;
	y = tmp - a / b * y;
   return Gcd;
}

int main()
{
	int a, b;
	scanf("%d%d", &a, &b);
	exgcd(a, b);
	printf("%d %d\n", x, y);
	return 0;
}

现在来考虑如何求出方程

\[ax+by=c \]

的整数解,其中 \(a,b,c\) 均为整数.

首先,由裴蜀定理知有整数解的充要条件为 \(\gcd(a,b)\mid c\).

\(\gcd(a,b)\nmid c\) 时,方程无整数解.

\(\gcd(a,b)\mid c\) 时,先求出满足

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

的整数 \(x',y'\),那么少了 \(\frac{c}{\gcd(a,b)}\) 倍,故令 \(x=x'\cdot\frac{c}{\gcd(a,b)},y=y'\cdot\frac{c}{\gcd(a,b)}\),即可使 \(ax+by=c\).

通解:

假设已经得到了一组解 \(\begin{cases}x=x_1\\y=y_1\end{cases}\),那么方程的通解可表示成 \(\begin{cases}x=x_1+bt\\y=y_1-at\end{cases}\)\(t\) 为整数)

这个非常显然,手推一下就出来啦。

练习:P5656 【模板】二元一次不定方程 (exgcd)


线性同余方程

P1082 [NOIP2012 提高组] 同余方程

求出关于 \(x\) 的同余方程

\[ax\equiv1\pmod b \]

的最小 整数解,其中 \(a,b\) 均为整数.

考虑将原方程转化成

\[ax+by=1 \]

其中 \(y\) 为整数.

题目保证有解,说明这个方程也一定有解,直接用扩欧.

注意要求的是最小 整数解,所以得转成整数.

\(\text{Code}\)

#include <iostream>
#include <cstdio>
#define int long long
using namespace std;

int x, y;

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

signed main()
{
	int a, b;
	scanf("%lld%lld", &a, &b);
	exgcd(a, b);
	printf("%lld\n", (x % b + b) % b);
	return 0;
}

练习:P1516 青蛙的约会

posted @ 2021-10-27 18:47  mango09  阅读(85)  评论(0编辑  收藏  举报
-->