扩展欧几里得

输入两个数a,b

求x,y满足

a*x+b*y=gcd(a,b)

比如说输入3,5 

解出来x=2,y=-1

所以说,怎么解?

我们假设已经求出x1,y1使

b*x1+(a%b)*y1=gcd(b,a%b)

成立

那么x1与x,y1与y的关系是什么呢

因为

gcd(a,b)=gcd(b,a%b)

所以

a*x+b*y==b*x1+(a%b)*y1

即([]为取整)

a*x+b*y==b*x1+(a-b*[a/b])*y1

右边展开再分配

a*x+b*y==a*y1+b*(x1-[a/b]*y1)

发现

x==y1 , y==x1-[a/b]*y1时成立

于是我们就能递归,边界?

当b==0时,gcd(a,b)=a,x=1,y=0

 


举个例子

求x,y满足5*x+3*y==1

我们递归下去,发现要求出这个x1,y1

3*x1+2*y1==1

继续,要求x1,y1就要求x2,y2

2*x2+1*y2==1

继续,要求x2,y2就要求x3,y3

1*x3+0*y3==1


遇到边界,即b==0,都搞定了

1.a==1,b==0

x3 = 1 , y3 = 0  ->  1*1+0*0=1

2.a==2,b==1

x2 = y3 = 0 , y2 = x3 - [a/b] * y3 = 1 - [2/1] * 0 = 1  ->  0*2+1*1=1

3.a==3,b==2

x1 = y2 = 1 , y1 = x2 - [a/b] * y2 = 0 - [3/2] * 1 = -1  ->  1*3+(-1)*2=1

4.a==5,b==3

x = y1 = -1 , y = x1 - [a/b]*y1 = 1 - [5/3] * (-1) = 2  ->  (-1)*5+(2)*3=1


是不是觉得特别巧妙

实在不理解先背代码

void exgcd(int a,int b)
{
	if(b==0) g=a,x=1,y=0;
	else{
		exgcd(b,a%b);
		int x1=y,y1=x-a/b*y;
		x=x1,y=y1;
		printf("%d*(%d)+%d*(%d)=%d\n",a,x,b,y,g);
	}
}

输出来是

并且 

int tmp=gcd(a,b)

若a*x+b*y=tmp成立

a*(x+b/tmp)+b*(y-a/tmp)=tmp成立

即 5*2+3*(-3)=1 , 5*5+3*(-8)=1 ...


应用

同余方程(NOIP2012提高组)

a*x=b*k+1

a*x-k*b=1 , 令y=-k

a*x+b*y=1

找出一组最小正整数解即可

若x<0 x+=b

青蛙的约会

设跳了k步

(x+m*k)%L==(y+n*k)%L

(x+m*k)-(y+n*k)=L*q(q为整数)

k*(m-n)-L*q=y-x

设a=k , x=m-n , b=-L , y=q , tmp=y-x

a*x+b*y=tmp

若tmp!=gcd(a,b) 无解

答案为最小正整数解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值