您的位置:首页 > 其它

欧几里得算法及其拓展

2017-05-25 19:10 169 查看
欧几里得算法,就是辗转相除法,来求最大公约数

求线段上格点的个数

参考 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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: