扩展欧几里得

扩展欧几里得算法的最大用法就是用来计算二元一次方程的整数解。

**贝祖定理:**即如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。

或者说二元一次方程有解的充要条件就是二元一次方程(ax + by = c)有解的充要条件就是 c 是 gcd(a, b) 的整数倍

这时候使用扩展欧几里得就可以求得二元一次方程的一个解。

当到达递归边界的时候,b==0,a=gcd(a,b) 这时可以观察出来这个式子的一个解:a1+b0=gcd(a,b),x=1,y=0,注意这时的a和b已经不是最开始的那个a和b了,所以我们如果想要求出解x和y,就要回到最开始的模样。

​ 初步想法:由于是递归的算法,如果我们知道了这一层和上一层的关系,一层一层推下去,就可以推到最开始的。类似数学上的数学归纳法。

​ 假设当前我们在求的时a和b的最大公约数,而我们已经求出了下一个状态:b和a%b的最大公因数,并且求出了一组x1和y1使得 b*x1+(a%b)*y1=gcd

(注意在递归算法中,永远都是先得到下面一个状态的值)

这时我们可以试着去寻找这两个相邻状态的关系:

首先我们知道:a%b=a-(a/b)*b;带入:

b*x1 + (a-(a/b)*b)*y1

= bx1 + ay1 – (a/b)by1

= ay1 + b(x1 – a/by1) = gcd 发现 x = y1 , y = x1 – a/by1

这样我们就得到了每两个相邻状态的x和y的转化,就可以在求gcd的同时对x和y进行求值了。

板子:

#include<iostream>
#include<cstdio>
#include<cmath>
 
using namespace std;
 
int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法
{
    if(b==0)
    {
        x=1;y=0;
        return a;  //到达递归边界开始向上一层返回
    }
    int r=exgcd(b,a%b,x,y);
    int temp=y;    //把x y变成上一层的
    y=x-(a/b)*y;
    x=temp;
    return r;     //得到a b的最大公因数
}

这里还有一个裸题用来应用扩展欧几里得算法:

http://poj.org/problem?id=1061

题目意思理解清楚了之后,可以看出根据题目意思列出一个二元一次方程(m + n)a + Lb = y-x。

//扩展欧几里得 
#include<iostream>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
typedef long long ll;
ll ex_gcd(ll a, ll b, ll &x, ll &y){
	if(!b){
		x = 1;
		y = 0;
		return a;
	}
	ll d = ex_gcd(b, a%b, x, y);
	ll t = x;
	x = y;
	y = t - (a/b) * y;
	return d;
} 
void solve(ll a, ll b, ll c){
	ll x, y;
	ll d = ex_gcd(a, b, x, y);	// d是 a,b最大公约数 
	if( c % d ){	//无解情况 
		cout << "Impossible" << endl;
		return ;
	}
	x = x * c / d;	// 求一个解 因为你之前求的  gcd(a,b)的解,所以现在需要乘c。 
	ll t = b / d;
	if(t < 0)
		t = -t;
	x = (x%t + t) % t;
	cout << x << endl; 
	return ;
}
int main(){
	int x, y, m, n, L;
	while(cin >> x >> y >> m >> n >> L){
		solve(m-n, L, y-x);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值