欧几里得算法及其拓展

欧几里得算法,就是辗转相除法,来求最大公约数

求线段上格点的个数
参考 https://zhidao.baidu.com/question/626799132816882324.html
题目描述
给定平面上的两个格点P1=(x1,y1)和P2=(x2,y2),线段P1P2上,除P1和P2以外一共有几个格点并打印出格点坐标?
限制条件:
-1000000000<=x1,y1,x2,y2<=1000,000,000
输入
P1=(1,11),P2=(5,3)
输出
(2,9)、(3,7)、(4,5)三个点
批注:格点是指横纵坐标均为整数的点。

一开始,格点还不好计算呀,直接枚举判断呗,这个时候时间复杂度就为O(|x1-x2|*|y1-y2|)。但是我们看这里x和y的范围都到 了1e9,这个时间复杂度就会超时。如果将斜率先算出来,然后扫一遍x的范围,来判断是不是格点,这个时候时间复杂度为O(|x1-x2|)。我们还有一种log的时间复杂度,就是我们发现答案就是|x1-x2|和|y1-y2|的最大公约数-1(因为我们可以从图中可以看出来最后一点也算进去了),然后对|x1-x2|=0,|y1-y2|=0,的情况特判,应该为0;
这里写图片描述

为什么是他们的最大公约数呢。其实这里的最大公约数就相当于他们的最大的公共等分数,比如
x1=1,y1=11
x2=5,y2=3

|x1-x2|=4,|y1-y2|=8,他们的最大公约数为4,表示他们都可以整分成4分,然后这四分的点都是整点。其中最后一个整点会落在我们给的点上(为什么?可以用反证法),最后要-1~

//求最大公约数
int gcd(int a,int b)
{
     if(b==0) return a;
     else return gcd(b,a%b);
}

双六
参考http://blog.csdn.net/zhjchengfeng5/article/details/7786595
题意:给你a和b的值,问你 ax+by=1有没有解,如果有的话,输出。没有的话输出-1.
我们知道如果gcd(a,b)是a,b的最大公约数的话,则ax+by也可以整除gcd(a,b).
如果gcd(a,b)不为1的话,则无解。
假设当前我们要处理的是求出 a 和 b的最大公约数,并求出 x 和 y 使得 a*x + b*y= gcd ,而我们已经求出了下一个状态:b 和 a%b 的最大公约数,并且求出了一组x1 和y1 使得: b*x1 + (a%b)*y1 = gcd , 那么这两个相邻的状态之间是否存在一种关系呢?
我们知道: a%b = a - (a/b)*b(这里的 “/” 指的是整除,例如 5/2=2 , 1/3=0),那么,我们可以进一步得到:
gcd = b*x1 + (a-(a/b)*b)*y1
= b*x1 + a*y1 – (a/b)*b*y1
= a*y1 + b*(x1 – a/b*y1)
对比之前我们的状态:求一组 x 和 y 使得:a*x + b*y = gcd ,是否发现了什么?
这里:
x = y1
y = x1 – a/b*y1
以上就是扩展欧几里德算法的全部过程,依然用递归写:

void extgcd(int a,int b,int &x,int &y)
{
   if(b==0)
   {
       x=1,y=0;
       return ;
   }
   else{
    extgcd(b,a%b,x,y);
    int temp=y;
    y=x-(a/b)*y;
    x=temp;
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值