扩展欧几里得算法及其简单应用

本文介绍了整除与取模的运算规则,并详细阐述了欧几里得算法用于计算最大公约数的原理及性质。通过递归关系展示了gcd(a,b)=gcd(b,a%b)的等价性。接着讨论了最大公约数和最小公倍数的计算方法,并给出了扩展欧几里得算法来求解线性同余方程ax+by=n的解。此外,还提到了逆元的概念及其在避免除法取模操作中的作用。最后,探讨了同余方程的解法和逆元在程序设计中的实用价值。
摘要由CSDN通过智能技术生成

1. 整除与取模

先普及一下整除符号“|”
对于整数a,b(a≠0),若存在整数k,使b=ka,则称a整除b,或b能被a整除,记为a∣b

然后是取模运算

取模运算不用说,大家都懂,不过有几条性质希望大家也都明白。

(a+b)%m = (a%m + b%m ) %m;

(a-b)%m = (a%m - b%m ) %m;

(a*b)%m = (a%m * b%m ) %m;

除法在这里是不成立的:(a/b)%m = (a%m / b%m ) %m; 这是错误的

2. 欧几里得算法

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)

a < b a<b a<b,则 g c d ( a , b ) = g c d ( b , a ) = g c d ( b , a % b ) gcd(a,b)=gcd(b,a)=gcd(b,a\% b) gcd(a,b)=gcd(b,a)=gcd(b,a%b),命题成立。

a > = b a>=b a>=b,不妨设 a = q ∗ b + r a=q*b+r a=qb+r,其中 0 ≤ r < b 0≤r<b 0r<b。显然 r = a r=a%b r=a。 对于 a , b a,b a,b的任意公约数 d d d,
因为 d ∣ a d|a da, d ∣ ( q b ) d|(qb) d(qb),故 d ∣ ( a − q b ) d|(a-qb) d(aqb), 即 d ∣ r d| r dr, 因此 d d d也是 b , r b,r b,r的公约数。 对于 b , r b,r b,r的任意公约数 k k k, 因为 k ∣ b , k ∣ ( a − q b ) k|b, k|(a-qb) kb,k(aqb)[注意 r = a − q b r=a-qb r=aqb], 故 k ∣ a k|a ka,因此 k k k也是 a , b a,b a,b的公约数 故 a , b a,b a,b的公约数集合与 b , a b,a%b b,a的公约数集合相同。于是它们的最大公约数自然也相等。

如果觉得不自然,请再往下看。

假设 ( a , b ) > ( b , a % b ) (a,b)>(b,a\%b) (a,b)>(b,a%b),令 d d d等于 a , b a,b a,b的最大公约数,即 d = ( a , b ) d=(a,b) d=(a,b)
根据上面的推导可知: d d d同时也是 b , r b,r b,r的公约数,而 b , r b,r b,r的最大公约数一定大于等于 d d d,假设不成立
假设 ( a , b ) < ( b , a % b ) (a,b)<(b,a\%b) (a,b)<(b,a%b),和上面一样的道理,假设不成立。 ( a , b ) (a,b) (a,b)既不大于也不小于 ( b , a % b ) (b,a\%b) (b,a%b),两者相等。

3. 最大公约数、最小公倍数

int gcd(int a,int b)//最大公约数
{
	if(b==0) return a;
    return gcd(b,a%b);
}
//gcd(a,b)=gcd(b,a%b)=====>>>>>>gcd(a,0)=a;
//(16,24)=(24,16%24)==>(24,8)=(8,24%8)=(8,0)=0;
int lcm(int a,int b)//最小公倍数  = a*b/gcd(a,b)
{
    return a/gcd(a,b)*b;
}

4. 扩展欧几里得算法

满足ax+by=(a,b) 时,可以用扩展欧几里得算法求出一组特解 ( x0 , y0 )

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

a x + b y = b x + ( a % b ) y = a y + ( x − a / b ∗ y ) b ax+by = bx+(a\%b)y = ay + ( x -a/b*y)b ax+by=bx+(a%b)y=ay+(xa/by)b

于是我们可以不断递归至 b = 0 b=0 b=0,使得 a x + b y = ( a , 0 ) = a , x = 1 , y = 0 ; ax+by=(a,0)=a,x=1,y=0; ax+by=(a,0)=a,x=1,y=0;

5. ax+by=n

5.1 有解条件

当且仅当 n 是 g c d ( a , b ) 的倍数时,才有整数解。 当且仅当n是gcd(a,b)的倍数时,才有整数解。 当且仅当ngcd(a,b)的倍数时,才有整数解。

5.2 求解步骤

1. 判断 a x + b y = n 是否有整数解,有解的条件是 g c d ( a , b ) ∣ n 2. 求 a x + b y = d = ( a , b ) 的一个解 ( x 0 , y 0 ) 3. 在得到的 a x 0 + b y 0 = d 两边同时乘 n / d 得到   a x 0 ∗ n / d + b y 0 ∗ n / d = n 4. 对照 a x + b y = n 得到它的一个解 x = x 0 ∗ n / d ,    y = y 0 ∗ n / d 5. 它的通解表达式为  x = x + b / d      y = y − a / d 1.判断ax+by=n 是否有整数解,有解的条件是 gcd(a,b)|n\\ 2.求ax+by= d=(a,b) 的一个解 (x_0, y_0) \\ 3.在得到的 ax_0+by_0 = d 两边同时乘 n/d 得到 \ \ ax_0 *n/d+by_0 *n/d = n\\ 4.对照 ax+by=n 得到它的一个解 x = x_0 *n/d,\ \ y = y_0 *n/d \\ 5.它的通解表达式为 \ x=x+b/d\ \ \ \ y=y-a/d\\ 1.判断ax+by=n是否有整数解,有解的条件是gcd(a,b)n2.ax+by=d=(a,b)的一个解(x0,y0)3.在得到的ax0+by0=d两边同时乘n/d得到  ax0n/d+by0n/d=n4.对照ax+by=n得到它的一个解x=x0n/d,  y=y0n/d5.它的通解表达式为 x=x+b/d    y=ya/d

如果要求x的最小正整数解,令 t = b / d t=b/d t=b/d x = ( x % t + t ) % t x=(x\%t+t)\%t x=(x%t+t)%t 求y同理

5.3 代码

int solve(int a,int b,int n)  //ax+by=n
{
	int x,y;
	int d=exgcd(a,b,x,y);//x',y'
	if(n%d!=0) return -1;
    
	x=x*n/d;
	int t=b/d;//t<0
	if(t<0) t=-t;
	return (x%t+t)%t;  //x和y不一定同时到最小值
}

6. 同余方程

1.同余

两个整数a、b和正整数m ,如果a除以m所得的余数和b除以m所得的余数相等,即a %m=b%m.

称a和b对于m同余.m称为同余的模。同余的概念也可以这样理解: m l(a-b)。即a-b是m的整数倍。

例如 6|(16-4)16和4对6同余。同余的符号记为
a ≡ b ( m o d m ) a \equiv b(mod \quad m) ab(modm)

2.同余方程

a x ≡ b ( m o d m ) ax \equiv b(mod \quad m) axb(modm)

a x − b 是 m 的整数倍,即满足 a x − b = m y   其中 y 可以是负数 于是可以改写为 a x + m y = b ax-b 是m的整数倍,即满足ax-b=my \ \ 其中y可以是负数\\ 于是可以改写为 ax+my=b axbm的整数倍,即满足axb=my  其中y可以是负数于是可以改写为ax+my=b

于是解同余方程就变成了求解二元一次不定方程,用扩展欧几里得算法,有解条件是gcd(a,m)能整除b

7. 逆元

什么是逆元?百度百科:逆元

这里只讨论我们需要的乘法逆元:
满足 a x ≡ 1 ( m o d   m ) 的 x ,称为 a 在模 m 下的逆元,即 a x 模 m 等于 1 满足ax \equiv 1(mod \ m)的x,称为a在模m下的逆元,即ax模m等于1 满足ax1(mod m)x,称为a在模m下的逆元,即axm等于1

ax+my=1
ax+by=n=1
int slove(int a,int m)
{
	int x,y;
	exgcd(a,m,x,y);
	return (x%m+m)%m;
}
除法取模

逆元有什么用?

求(a/b)%m时,当a,b是很大的数时,作除法会损失精度

使用逆元可以避免除法:设k是b的逆元,则bk%m=1
( a b % m ) = ( a b % m ) ∗ b k % m = a k % m (\frac{a}{b}\% m)=(\frac{a}{b}\% m)*bk\%m=ak\%m (ba%m)=(ba%m)bk%m=ak%m
于是a/b就变成了ak,是不是很nice

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值