扩展欧几里得

扩展欧几里得

经典问题,找出一对整数,使得ax+by=gcd(a,b)
gcd表示最小公约数,代码附上:

int gcd(int a,int b)
{
 return b?gcd(b,a%b):a;
}

假设上述函数的一个特解(x0,y0)根据二元一次不定方程的解法可得
x=x0+b/gcd;
y=y0-a/gcd;
得到它的通解形式,所以我们只要求出它的一个特解就好了,怎么求这个特解呢?
让我们来分析一下gcd的过程最后一个状态是gcd(a,0)也就是 a1+0b=gcd;a=gcd;
由欧几里得我们知道gcd(a,b)=gcd(b,a%b);
bx0+(a%b)y0=gcd
a%b=a-(a/b)b;除法为向下取余的除法
代入得到式子 b
x0+(a-(a/b)b)y0=gcd;
化简 a
y0+b
(x0+a/b
y0)=gcd
对比a
x+by=gcd得到
x=y0
y=x0+a/b
y0;
所以得出下面代码

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

这是一道简单例题,不过有了最小整数的条件,可以去尝试尝试https://vjudge.net/problem/HDU-2669
AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include<set>
using namespace std;
#define fin(a,n) for(int i=a;i<=n;i++)
#define fjn(a,n) for(int j=a;j<=n;j++)
#define fkn(a,n) for(int k=a;k<=n;k++)
#define ll long long int
#define maxn 20000
ll exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得;
{
	if(b==0)
	{x=1;y=0;return a;}
	int g=exgcd(b,a%b,x,y);
	int cnt=y;
	y=x-(a/b)*y;
	x=cnt;
	return g;
}
ll gcd(ll a,ll b)//普通欧几里得
{
	return b?gcd(b,a%b):a;
}
int main()
{
	ll a,b,x,y;
	while(scanf("%lld %lld",&a,&b)!=EOF)
	{   
		if(gcd(a,b)==1)
		{
		exgcd(a,b,x,y);
		x%=b;//此处为该题多的地方,x可为正负,若为正,直接对b取余,
		//若为负,取余后再+上相应的b变成正数就好,具体请自学负数的取余
		while(x<0)x+=b;
		y=(1-a*x)/b;
		printf("%lld %lld\n",x,y);
	    }
		else printf("sorry\n");
	}
}

数论持续中、、、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值