【刷题】数学知识——扩展欧几里得、裴蜀定理

裴蜀定理

1 定理

裴蜀定理

a , b a, b a,b是不全为零的整数,则一定存在整数 x , y x, y x,y, 使得 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)

换句话说,若 a , b a, b a,b是不全为零的整数,则 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)一定存在整数解 x , y x, y x,y
证明过程在上面的链接中。
求出整数解的过程就是扩展欧几里得算法

2 推论

d = g c d ( a , b ) d=gcd(a,b) d=gcd(a,b),由于 a a a b b b分别去掉最大公因数 d d d后,二者不再有公因子,即 a d \frac{a}{d} da b d \frac{b}{d} db是互质的
a ′ = a d a'=\frac{a}{d} a=da b ′ = b d b'=\frac{b}{d} b=db a x + b y = d ax+by=d ax+by=d左右同除 d d d,得到如下推论:
推论1

a ′ a' a b ′ b' b互质,则方程 a ′ x + b ′ y = 1 a'x+b'y=1 ax+by=1有整数解。

此外还可证明推论2

若方程 a ′ x + b ′ y = 1 a'x+b'y=1 ax+by=1有整数解,则 a ′ a' a b ′ b' b互质

反证:若 a ′ a' a b ′ b' b不互质,则有 a ′ = g c d ( a ′ , b ′ ) ∗ p a'=gcd(a',b')*p a=gcd(a,b)p b ′ = g c d ( a ′ , b ′ ) ∗ q b'=gcd(a',b')*q b=gcd(a,b)q,此处 p , q p,q p,q为互质的整数。
代入方程中,得到:
g c d ( a ′ , b ′ ) ∗ p ∗ x + g c d ( a ′ , b ′ ) ∗ q ∗ y = 1 gcd(a',b')*p*x+gcd(a',b')*q*y=1 gcd(a,b)px+gcd(a,b)qy=1
左右同除 g c d ( a ′ , b ′ ) gcd(a',b') gcd(a,b)
p ∗ x + q ∗ y = 1 g c d ( a ′ , b ′ ) p*x+q*y=\frac{1}{gcd(a',b')} px+qy=gcd(a,b)1
由于 a ′ a' a b ′ b' b不互质,则 g c d ( a ′ , b ′ ) > 1 gcd(a',b')>1 gcd(a,b)>1 1 g c d ( a ′ , b ′ ) \frac{1}{gcd(a',b')} gcd(a,b)1是小数,所以 x x x y y y不可能是整数,方程 a ′ x + b ′ y = 1 a'x+b'y=1 ax+by=1没有整数解,矛盾。

结合推论1和推论2,可得到裴蜀定理推论

a ′ a' a b ′ b' b互质的充要条件是方程 a ′ x + b ′ y = 1 a'x+b'y=1 ax+by=1有整数解

3 判断不定方程是否有整数解

a x + b y = z ax+by=z ax+by=z有整数解的充要条件是 g c d ( a , b ) ∣ z gcd(a,b)|z gcd(a,b)z

1、若 z z z能整除 g c d ( a , b ) gcd(a,b) gcd(a,b),则 a x + b y = z ax+by=z ax+by=z有整数解
z = k ∗ g c d ( a , b ) z=k*gcd(a,b) z=kgcd(a,b)
由裴蜀定理知存在整数解 x ′ , y ′ x',y' x,y使得 a x ′ + b y ′ = g c d ( a , b ) ax'+by'=gcd(a,b) ax+by=gcd(a,b)
a x + b y = z ax+by=z ax+by=z相当于 a k x ′ + b k y ′ = k ∗ g c d ( a , b ) akx'+bky'=k*gcd(a,b) akx+bky=kgcd(a,b)
整数解是 x = k x ′ x=kx' x=kx y = k y ′ y=ky' y=ky

2、若 a x + b y = z ax+by=z ax+by=z有整数解,则 z z z能整除 g c d ( a , b ) gcd(a,b) gcd(a,b)
证明类似推论2
反证:若 z z z不能整除 g c d ( a , b ) gcd(a,b) gcd(a,b)
a x + b y = z ax+by=z ax+by=z两边同除 g c d ( a , b ) gcd(a,b) gcd(a,b)
a ′ x + b ′ y = z g c d ( a , b ) a'x+b'y=\frac{z}{gcd(a,b)} ax+by=gcd(a,b)z,其中 a ′ = a g c d ( a , b ) a'=\frac{a}{gcd(a,b)} a=gcd(a,b)a b ′ = b g c d ( a , b ) b'=\frac{b}{gcd(a,b)} b=gcd(a,b)b是互质的整数
由于 z g c d ( a , b ) \frac{z}{gcd(a,b)} gcd(a,b)z是小数,所以 x x x y y y不可能是整数,方程 a x + b y = z ax+by=z ax+by=z没有整数解,矛盾。

4 推广到n元

对不定方程 a 1 x 1 + a 2 x 2 + . . . + a n x n = z a_1x_1+a_2x_2+...+a_nx_n=z a1x1+a2x2+...+anxn=z,满足 g c d ( a 1 , a 2 , . . . , a n ) ∣ z gcd(a_1,a_2,...,a_n)|z gcd(a1,a2,...,an)z时,方程才有整数解

g c d ( a 1 , a 2 , . . . , a n ) = 1 gcd(a_1,a_2,...,a_n)=1 gcd(a1,a2,...,an)=1的充要条件是不定方程 a 1 x 1 + a 2 x 2 + . . . + a n x n = 1 a_1x_1+a_2x_2+...+a_nx_n=1 a1x1+a2x2+...+anxn=1有整数解


扩展欧几里得

在这里插入图片描述
利用辗转相除法可以顺便得到x和y。
辗转相除法过程如下:

int exgcd(int a, int b) {
    if(!b) {
    	return a;
    }
    else {
		return exgcd(b, a % b);
	}
}

当b=0时,可以看出ax+by=gcd(a,b)的一组解是x=1,y=0。于是有:

    if(!b) {
    	x = 1, y = 0;
    	return a;
    }

在进行辗转时, a ′ = b a'=b a=b b ′ = a % b b'=a\%b b=a%b,带入 a ′ x + b ′ y = d a'x+b'y=d ax+by=d中可得 b x + ( a % b ) y = d bx+(a\%b)y=d bx+(a%b)y=d
a % b a\%b a%b可以写成 a − ⌊ a / b ⌋ ∗ b a-\lfloor a/b \rfloor * b aa/bb
所以有 b x + ( a − ⌊ a / b ⌋ b ) y = d bx+(a-\lfloor a/b \rfloor b)y=d bx+(aa/bb)y=d
我们想知道a和b的整数解x和y,因此要提出a和b,a和b的系数就是下一轮的x’和y’。
上式变为 a y + b ( x − ⌊ a / b ⌋ y ) = d ay+b(x-\lfloor a/b \rfloor y)=d ay+b(xa/by)=d
于是有 x ′ = y , y ′ = ( x − ⌊ a / b ⌋ y ) x'=y, y'=(x-\lfloor a/b \rfloor y) x=y,y=(xa/by)

    else {
		int d = exgcd(b, a % b, x, y);
		int tmp = x;
		x = y;
		y = tmp - a / b * y;
		return d;
	}

为了便于书写,可以交换递归时x和y的位置,省掉中间变量tmp

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

该题代码如下

#include <iostream>
using namespace std;
int n, a, b, x, y;

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

int main() {
	scanf("%d", &n);
	while(n -- ) {
		scanf("%d%d", &a, &b);
		exgcd(a, b, x, y);
		printf("%d %d\n", x, y);
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值