二元一次方程的定义:
含有两个未知数,并且含有未知数的项的次数都是1的整式方程做二元一次方程。所有二元一次方程都可化为ax+by+c=0(a、b≠0)的一般式与ax+by=c(a、b≠0)的标准式,否则不为二元一次方程。
求最大公约数
int gcd(int a,int b)//a,b为两个数。
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
拓展欧几里得算法
int exgcd(int a,int b,int &x,int &y)
{
if(b==0){
x=1;
y=0;
return a;
}
else{
int r=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return r;
}
}
求一组特解代码:
if(n%__gcd(a,b) == 0){ //第一步判断方程是否有整数解
exgcd(a,b,x,y);//第二步求方程 ax+by=gcd(a,b) 的一个特解
x = x*n/__gcd(a,b); //第三步计算 ax+by=n 的解
y = y*n/__gcd(a,b);
cout<<x<<" "<<y<<endl;
}
求通解
现在我们来考虑构造通解( 特解是X、Y ):
由于已经满足 , 两个未知数的关系类似于加权和固定,若一个增大,则另一个一定按比例减小,显然满足关系:
X 每变化 b 的整数倍,Y 就反向变化 a 的同等倍数。似乎构造出了通解表达式 、 。
但是我们会发现一个问题,就是 a 、b 不一定是最小的步长,可能会 “跳过” 许多解。
为了求得最小步长,我们应该对 a 、b 同时除以某个整数,使得商也是整数,就求出了每次最小的变化量。很明显,应除以
所以,通解应该是
举例:(待修改)
for(int i=0;i<=1000;i++){
int newx = x+i*b/__gcd(a,b);
int newy = y-i*a/__gcd(a,b);
if(newx>=0&&newy>=0){
cout<<"newx= "<<newx<<" newy="<<newy<<endl;
}
}
参考:
https://blog.csdn.net/weixin_43810158/article/details/87973511
https://blog.csdn.net/Originum/article/details/81437027