直线上的点——扩展欧几里得算法

本文介绍了扩展欧几里得算法,用于求解直线ax+by=c上整数点的问题。通过算法分析,得出当c是gcd(a,b)的倍数时,存在整数解(x * c/g, y * c/g),反之无解。并提供了代码实现及实例验证。" 123913313,9754279,MindSpore ReduceSum维度错误解决方案,"['深度学习', 'MindSpore框架', '错误排查', '张量操作']
摘要由CSDN通过智能技术生成
问题:

求直线ax+by=c上有多少个整数点(x,y)满足x∈[x1,x2],y∈[y1,y2]。

分析:

为了解决这个问题,我们需要学习扩展欧几里得算法。我们知道欧几里得算法是求gcd(a,b)的,而扩展欧几里得算法则是求ax+by=gcd(a,b)时x和y的一组解。
不多说,直接把代码贴上:

void exgcd(int a,int b,int&d,int&x,int&y){
  if(!b){d=a;x=1;y=0;}
  else{exgcd(b,a%b,d,y,x);y-=x*(a/b);}
}

上面的代码求出了一组解,那么其它解呢?
设求出的解为(x1,y1),另一组解为(x2,y2),则ax1+by1=ax2+by2,变形得a(x1-x2)=b(y2-y1)。代码还求出gcd(a,b)=d,两边同时除以d,则a’(x1-x2)=b’(y2-y1),其中a’=a/d,b’=b/d。不难得出x1-x2是b’的整数倍。设倍数为k,可以计算得y2-y1=ka’。可以得出如下结论:

设a,b,c为任意整数,若方程ax+by=c的一个解是(x,y),则任意整数解都可以表示为(x+kb’,y-ka’),其中a’=a/gcd(a,b),b’=b/gcd(a,b),k取任意整数。

注意:在c不是gcd(a,b)的倍数时无解
举两个例子,自行验证一下:
例1:6x+15y=9,代码求出6 * (-2)+15 * 1=3,两边同时乘3得6 * (-6)+15 * 3=9,所以x=-6,y=3时6x+15y=9。
例2:6x+15y=8,因为gcd(6,15)=3,不是8的倍数,无解。
有如下结论:

设a,b,c为任意整数,g=gcd(a,b),方程ax+by=g时的一组解为(x,y),则当c是g的倍数时ax+by=c的一组解是(x * c/g,y * c/g),当c不是g的倍数时无解。

代码如下:
注:如果题目要求的直线方程是ax+by+c=0,那么只需要在for的开头输入c后加一句c=-c即可,因为它移项后可以变成ax+by=-c。
#include <iostream>
#include <cmath>
using namespace std;
void gcd(int a,int b,int&d,int&x,int&y){
  if(!b){d=a;x=1;y=0;}
  else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
int main(){
  int a,b,c,d,x,y,x0,x1,y0,y1;
  for(int o_o=0;cin>>a>>b>>c;o_o++){
    cin>>x0>>x1>>y0>>y1;
    if(o_o)cout<<endl;
    gcd(a,b,d,x,y);
    if(c%d){cout<<"No answer."<<endl;continue;}
    int bei=c/d;
    a/=d;b/=d;x*=bei;y*=bei;
    int mink=max(ceil (1.0*(x0-x)/b),ceil (1.0*-(y1-y)/a));
    int maxk=min(floor(1.0*(x1-x)/b),floor(1.0*-(y0-y)/a));
    if(maxk<mink)cout<<"No answer."<<endl;
    else if(maxk==mink) cout<<"There is 1 answer."<<endl;
    else cout<<"There are "<<(maxk-mink+1)<<" answers."<<endl;
    for(int k=mink;k<=maxk;k++)
      cout<<"("<<x+k*b<<","<<y-k*a<<")"<<endl;
  }
  return 0;
}

输入样例1:

1 2 3
-10 10 -10 10
6 15 8
-10 10 -10 10

输出样例1:

There are 10 answers.
(-9,6)
(-7,5)
(-5,4)
(-3,3)
(-1,2)
(1,1)
(3,0)
(5,-1)
(7,-2)
(9,-3)

No answer.

输入样例2:

6 15 9
-20 20 -20 20
6 15 9
1 1 1 1
6 15 9
-1 -1 1 1

输出样例2:

There are 8 answers.
(-16,7)
(-11,5)
(-6,3)
(-1,1)
(4,-1)
(9,-3)
(14,-5)
(19,-7)

No answer.

There is 1 answer.
(-1,1)

输入样例3:

99 78 14
-50 50 -50 50
99 78 15
-50 50 -50 50

输出样例3:

No answer.

There are 3 answers.
(-29,37)
(-3,4)
(23,-29)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值