贝祖等式:对于不完全为0的两个非负整数,a,b;gcd(a,b)表示这两个数的最大公约数,则必然存在整数x,y,使得gcd(a,b)=ax+by。
对于给定的符合条件的a,b;如何求出相应的x,y呢?
用扩展欧几里得算法解决该问题。
先给出代码实现,再分析算法原理:
代码一(较为简单,来源360百科):
#include <iostream>
using namespace std;
int x,y,p;
void Ep_gcd(int a,int b){
if(b==0) {x=1;y=0;p=a;return;}
Ep_gcd(b,a%b);
int tem=x;
x=y;
y=tem-a/b*x;
}
int main()
{
int a,b;
while(cin>>a>>b){
Ep_gcd(a,b);
cout<<"x is :"<<x<<"y is :"<<y<<endl;
}
return 0;
}
代码二(较为精炼,来源百度百科)
#include <iostream>
using namespace std;
void Ep_gcd(int a,int b,int&d,int &x,int &y)
{
if(b==0) {d=a;x=1;y=0;return;}
Ep_gcd(b,a%b,d,y,x);
y-=a/b*x;
}
int main()
{
int x,y,d,a,b;
while(cin>>a>>b){
Ep_gcd(a,b,d,x,y);
cout<<x<<' '<<y<<endl;
}
return 0;
}
下面就来讲讲这个算法的实现原理:
由扩展欧几里得定理:
ax+by=gcd(a,b);
由欧几里得定理可以知道gcd(a,b)=gcd(b,a%b);
证:另r=a%b;则a=kb+r;
设d为a和b的公约数,则d|a,d|b;
由r=a-kb;则d|r。
设d为b和r的公约数,则d|b,d|r;
又a=kb+r;故d|a;
所以由上得到a,b,r的公约数相同,则他们的最大公约数也相同。
进一步分析:
由gcd(a,b)=gcd(b,a%b)得一下两个等式:
x1a+y1b=gcd(a,b);
x2b+y2a%b=gcd(b,a%b);
有x1a+y1b=x2b+y2a%b;
a%b=a-a/b*b;
化简得到x1a+y1b=y2a+b(x2-a/b*y2);
由系数对应关系得到:x1=y2;y1=x2-a/b*y2;
扩展欧几里得算法的应用:
问题:【直线上的点】 求直线ax+by+c=0上有多少个整点(x,y)满足x∈[x1,x2],y∈[y1,y2]
分析:
首先我们可以利用扩展欧几里得算法得到ax+by=gcd(a,b)的一组解(x1,y1),那么思考一下其他解呢?
任取另外一组解(x2,y2),有ax1+by1=ax2+by2;变形得到a(x1-x2)=b(y2-y1);
左右两边分别除以gcd(a,b),令a`=a/gcd(a,b),b`=b/gcd(a,b);
即a`(x1-x2)=b`(y2-y1);由于a`和b`互质,故而看ka`=(y2-y1),kb`=(x1-x2),其中k为任意整数。
则分别得到x2=x1-kb`,y2=y1+ka`;k可以取任意整数。
有了这样的结论,回到该问题,经过移项得到ax+by=-c;
可以推知如果-c是gcd(a,b)的整数倍时,则该方程有整数解,且设ax+by=gcd(a,b)的一组解为(x0,y0);
则该方程的解为(x0*(-c)/g,y0*(-c)/g);
否则该方程无整数解