扩展欧几里德算法详解
内容:扩展欧几里德算法
是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd
(a, b) =d(解一定存在,根据数论
中的相关定理)。扩展欧几里德常用在求解模线性方程
及方程组中。
其实看了百度百科词条和好几种解释都让我头疼不已,昨天和老师讨论了一节课也没有什么好的结果,于是我今天用了一节历史课和一节信息课带了好几组数据终于明白了= =(感觉自己智商捉急)。
所以说为了大家不要像我一样智商捉急......咳咳。
——————————————————————————智慧的分割线————————————————————————————
首先我们都知道欧几里德的辗转相除法求最大公约数(不知道的自行百科),已知gcd(a,b)=gcd(b,a%b); 以上为扩欧的基础部分。然后我们假设有一个不定方程为ax+by=c,若要该方程有解,必要条件为c=k*gcd(a,b);(此处原因为,将方程整体系数全部除以gcd(a,b)后,前面的系数仍为整数,然而c若不为gcd(a,b)的倍数,除完以后将会变为一个非整数,显而易见,方程将不存在整数解。
于是我们假设ax+by=gcd(a,b)①; (c为gcd(a,b)的整数倍时,结果可以由此类推),那么由上述的欧几里德定理我们可以得到,ax+by=gcd(b,a%b),由数论相关基本定理我们又很容易得到必然存在这样一个成立的方程为:b*x1+(a%b)*y1= gcd(b,a%b)。而a%b=a-int(a/b)*b;所以我们可以将上式拆为: b*x1+( a-int(a/b)*b) *y1= gcd(b,a%b);合并同类项得:gcd(b,a%b)=a*y1+b*(x1-int(a/b)*b*y1)②;我们由①和②可以得到,x=y1,y= x1-int(a/b)*b*y1;于是我们一直一直算下去,最终必然会有一个点,a%b=0;这时候会发生什么呢...
此时的方程为:ax+0*y=a;那么易得x=1,y可以等于任意数,但由于题目常要求我们求方程的最小正整数解,我们此时将y置为0;然后电脑会一步一步帮我们递归回去...于是我们可以得到下面的代码= =(如果哪里写 的不好我改 (⊙o⊙) )
其实看了百度百科词条和好几种解释都让我头疼不已,昨天和老师讨论了一节课也没有什么好的结果,于是我今天用了一节历史课和一节信息课带了好几组数据终于明白了= =(感觉自己智商捉急)。
所以说为了大家不要像我一样智商捉急......咳咳。
——————————————————————————智慧的分割线————————————————————————————
首先我们都知道欧几里德的辗转相除法求最大公约数(不知道的自行百科),已知gcd(a,b)=gcd(b,a%b); 以上为扩欧的基础部分。然后我们假设有一个不定方程为ax+by=c,若要该方程有解,必要条件为c=k*gcd(a,b);(此处原因为,将方程整体系数全部除以gcd(a,b)后,前面的系数仍为整数,然而c若不为gcd(a,b)的倍数,除完以后将会变为一个非整数,显而易见,方程将不存在整数解。
于是我们假设ax+by=gcd(a,b)①; (c为gcd(a,b)的整数倍时,结果可以由此类推),那么由上述的欧几里德定理我们可以得到,ax+by=gcd(b,a%b),由数论相关基本定理我们又很容易得到必然存在这样一个成立的方程为:b*x1+(a%b)*y1= gcd(b,a%b)。而a%b=a-int(a/b)*b;所以我们可以将上式拆为: b*x1+( a-int(a/b)*b) *y1= gcd(b,a%b);合并同类项得:gcd(b,a%b)=a*y1+b*(x1-int(a/b)*b*y1)②;我们由①和②可以得到,x=y1,y= x1-int(a/b)*b*y1;于是我们一直一直算下去,最终必然会有一个点,a%b=0;这时候会发生什么呢...
此时的方程为:ax+0*y=a;那么易得x=1,y可以等于任意数,但由于题目常要求我们求方程的最小正整数解,我们此时将y置为0;然后电脑会一步一步帮我们递归回去...于是我们可以得到下面的代码= =(如果哪里写 的不好我改 (⊙o⊙) )
#include<cstdio>
using namespace std;
#define LL long long
LL a,b,x,y;
void exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1;//ax=a;
y=0;//最小值
return;
y=0;//最小值
return;
}
LL t;
exgcd(b,a%b,x,y);//递归
t=x;//因为下面的x要变化,所以用一个变量来记录x1值
x=y;//此处的y是递归回来的y1,此处体现传址调用的好处
y=t-a/b*y;//道理同上,
y=
x1-int(a/b)*b*y1
}
}
int main()
{
scanf("%lld%lld",&a,&b);
exgcd(a,b,x,y);
if(x<0)x+=b;//x要求为正整数
printf("%lld\n",x);
return 0;
}
———————————————————————————— Ends —————————————————————————————
———————————————————————————— Ends —————————————————————————————