(4)线性方程与最大公因数

线性方程定理

已知两个整数a,b。我们观察a的倍数加上b的倍数得到的所有可能的整数。也就是 a x + b y ax+by ax+by得到的所有整数,其中x与y可以为任意整数,注意x,y可以取到负值。

例如我们列出a=42,b=30的所有整数,通过观察发现所有的数都是6的倍数,这很好理解,因为42与30都可以被6整除, 42 x + 30 y = 6 ( 7 x + 5 y ) 42x+30y=6(7x+5y) 42x+30y=6(7x+5y)的每个数都是6的倍数。更一般的,显然形如 a x + b y ax+by ax+by的每一个数都可以被 g c d ( x , y ) gcd(x,y) gcd(x,y)整除,因为 g c d ( x , y ) gcd(x,y) gcd(x,y)可以整除a,b。

第二个观察是42与30最大公因数6出现在了表中。

42 ∗ ( − 2 ) + 30 ∗ 3 = 6 = g c d ( 42 , 30 ) 42*(-2)+30*3=6=gcd(42,30) 42(2)+303=6=gcd(42,30)

我们这时可以假设一个断言:

形如 a x + b y ax+by ax+by的最小正整数等于gcd(a,b)。

有许多方法可以证明这是成立的,我们可以利用欧几里得算法构造出合适的x,y,这里将计算过程列成表格,顺便与欧几里得算法过程进行对比。

a = 2 ∗ b + 16 a=2*b+16 a=2b+16 16 = a − 2 b 16=a-2b 16=a2b
b = 1 ∗ 16 + 6 b=1*16+6 b=116+6 6 = b − 1 ∗ 16 6=b-1*16 6=b116
  \, = b − 1 ∗ ( a − 2 b ) =b-1*(a-2b) =b1(a2b)
  \, = − a + 3 b =-a+3b =a+3b
16 = 2 ∗ 6 + 4 16=2*6+4 16=26+4 4 = 16 − 2 ∗ 6 4=16-2*6 4=1626
  \, = ( a − 2 b ) − 2 ∗ ( − a + 3 b ) =(a-2b)-2*(-a+3b) =(a2b)2(a+3b)
  \, = 3 a − 8 b =3a-8b =3a8b
6 = 1 ∗ 4 + 2 6=1*4+2 6=14+2 2 = 6 − 1 ∗ 4 2=6-1*4 2=614
  \, = ( − a + 3 a ) − 1 ∗ ( 3 a − 8 b ) =(-a+3a)-1*(3a-8b) =(a+3a)1(3a8b)
  \, = − 4 a + 11 b =-4a+11b =4a+11b
4 = 2 ∗ 2 + 0 4=2*2+0 4=22+0   \,

按这种方法我们每次都会获得形如

最新余数=a的倍数+b的倍数

的等式。最终得到最后的非零余数,这就是 g c d ( x , y ) gcd(x,y) gcd(x,y),得解。

现在我们知道 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)总有整数解(x,y),我们可以进一步讨论方程有多少个解以及怎么表示所有的解。
从特殊到一般,我们首先从互素的a,b开始,即让 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(ab)=1,假设(x1,y1)是

a x + b y = 1 ax+by=1 ax+by=1

方程的一个解。通过x1减去一个b的倍数和y1加上一个a的相同的倍数,可得到其他解,换句话说,对于任何整数k,我们得到了新解 ( x 1 + k b , y 1 − k a ) (x_1+kb,y_1-ka) (x1+kb,y1ka),通过计算

a ( x 1 + k b ) + b ( y 1 − k a ) = a x 1 + a k b + b y 1 − b k a = a x 1 + b y 1 = 1 a(x_1+kb)+b(y_1-ka)=ax_1+akb+by_1-bka=ax_1+by_1=1 a(x1+kb)+b(y1ka)=ax1+akb+by1bka=ax1+by1=1

可验证这确实是解。

同样我们也可以通过解方程推导出答案,仍然观察 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1的情况,假设(x1,y1),(x2,y2)是方程的两个解,则有:

a x 1 + b y 1 = 1 a x 2 + b y 2 = 1 ax_1+by_1=1\qquad ax_2+by_2=1 ax1+by1=1ax2+by2=1

我们用y2乘第一个方程,用y1乘第二个方程,相减就消去了b,重新整理后得到

a x 1 y 2 = a x 2 y 1 = y 2 − y 1 ax_1y_2=ax_2y_1=y_2-y_1 ax1y2=ax2y1=y2y1

类似地,如果用x2乘以第一个方程,用x1乘以第二个方程,再相减便得到

b x 2 y 1 − b x 1 y 2 = x 2 − x 1 bx_2y_1-bx_1y_2=x_2-x_1 bx2y1bx1y2=x2x1

如果令 k = x 2 y 1 − x 1 y 2 k=x_2y_1-x_1y_2 k=x2y1x1y2,则得到

x 2 = x 1 + k b 与 y 2 = y 1 + k a x_2=x_1+kb\quad与\quad y_2=y_1+ka x2=x1+kby2=y1+ka

这表明第二个解是由第一个解得到的,通过取不同的k可以得到每一个解 ( x 1 + k b , y 1 − k a ) (x_1+kb,y_1-ka) (x1+kb,y1ka)

如果 g c d ( a , b ) > 1 gcd(a,b)>1 gcd(a,b)>1的情况呢?我们令 g = g c d ( a , b ) g=gcd(a,b) g=gcd(a,b)由欧几里得一定可以得出

a x + b y = g ax+by=g ax+by=g

至少有一个解(x1,y2)而g整除a,b,故(x1,y1)也是简单方程

a g x + b g y = 1 \frac{a}{g}x+\frac{b}{g}y=1 gax+gby=1

的解,于是可以代入前面的方法得到解为 ( x 1 + k ∗ b g , y 1 − k ∗ a g ) (x_1+k*\frac{b}{g},y_1-k*\frac{a}{g}) (x1+kgb,y1kga)

线性方程定理设a,b是非零整数, g = g c d ( a , b ) g=gcd(a,b) g=gcd(a,b)。方程

a x + b y = g ax+by=g ax+by=g

总是有一个整数解(x1,y1),它可由前面的欧几里得算法得出,则方程的每一个解可由

( x 1 + k ∗ b g , y 1 − k ∗ a g ) (x_1+k*\frac{b}{g},y_1-k*\frac{a}{g}) (x1+kgb,y1kga)

得出,其中k为任意整数。

这节我们证明了方程 a x + b y = g ax+by=g ax+by=g总是有解,这个事实很重要,我们在接下来的数论中将多次用到。

算法代码

模拟上面的证明过程

int Eucild(int a1,int b1,int &x,int &y)
{
	int a=a1,b=b1;
	int r=a%b;
	x=1;
	int n=0,m=1,q;
	while(r)
	{		
		q=a/b;
		x=m-q*n;
		m=n;n=x;
		a=b;b=r;
		r=a%b;
	}
	y=(b-x*a1)/b1;
	return b;
}

但这并不是一个优秀的算法。(是我自己编的,太菜了)

接下来给出一个标准算法
对于一个方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)来说,我们可以做一下推导:
设有 a x 1 + b y 1 = g c d ( a , b ) ax_1+by_1=gcd(a,b) ax1+by1=gcd(a,b)
b x 2 + ( a % b ) y 2 = g c d ( b , a % b ) bx_2+(a\%b)y_2=gcd(b,a\%b) bx2+(a%b)y2=gcd(b,a%b)
对于这个方程组我们需要知道x1,x2,y1,y2的关系,才能递归的解决这个问题。
观察 b x 2 + ( a % b ) y 2 = g c d ( b , a % b ) bx_2+(a\%b)y_2=gcd(b,a\%b) bx2+(a%b)y2=gcd(b,a%b)这个式子其中 ( a % b ) (a\%b) (a%b)可以写为 a − ⌊ a b ⌋ ∗ b a-\lfloor\frac{a}{b}\rfloor*b abab。将括号打开合并a,b得

a y 2 + b ( x 2 + ⌊ a b ⌋ y 2 ) ay_2+b(x_2+\lfloor\frac{a}{b}\rfloor y_2) ay2+b(x2+bay2)

由于欧几里得算法的原理 g c d ( a , b ) = = g c d ( b , a % b ) gcd(a,b)==gcd(b,a\%b) gcd(a,b)==gcd(b,a%b),我们将两式子联立,对比系数即可得到 x 1 = y 2 , y 1 = x 2 − ⌊ a b ⌋ ∗ y 2 x_1=y_2,y_1=x_2−\lfloor ab\rfloor∗y_2 x1=y2,y1=x2aby2
这个递归的边界是什么呢?我们知道,当朴素欧几里得到达边界时, g c d ( a , 0 ) = a gcd(a,0)=a gcd(a,0)=a,那么边界条件就是对 a ∗ x 0 + b ∗ y 0 = a a∗x_0+b∗y_0=a ax0+by0=a求解,很显然,此时x0=1,y0=0

int eucild(int a,int b,int& x1,int& y1)
{
	if(!b)
	{
		x1=1,y1=0;
		return a;
	}
	int x2,y2;
	int d=exgcd(b,a%b,x2,y2);
	x1=y2,y1=x2-(a/b)*y2;
	return d;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值