扩展欧几里得算法求二元一次方程

二元一次方程的定义:

    含有两个未知数,并且含有未知数的项的次数都是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 ):

由于已经满足 aX+bY=c , 两个未知数的关系类似于加权和固定,若一个增大,则另一个一定按比例减小,显然满足关系:

a(X+nb)+b(Y-na)=c

X 每变化 b 的整数倍,Y 就反向变化 a 的同等倍数。似乎构造出了通解表达式 X+nb 、Y-na 。

但是我们会发现一个问题,就是 a 、b 不一定是最小的步长,可能会 “跳过” 许多解。

为了求得最小步长,我们应该对 a 、b 同时除以某个整数,使得商也是整数,就求出了每次最小的变化量。很明显,应除以

gcd(a, b)

所以,通解应该是

 X+n*b/gcd(a,b)\, \, ,\, \, Y-n*a/gcd(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

 

posted @ 2020-10-27 16:55  图神经网络  阅读(230)  评论(0编辑  收藏  举报
Live2D