欧几里德算法gcd及其拓展终极解释
这个困扰了自己好久,终于找到了解释,还有自己改动了一点点,耐心看完一定能加深理解
扩展欧几里德算法-求解不定方程,线性同余方程。
设过s步后两青蛙相遇,则必满足以下等式:
(x+m*s)-(y+n*s)=k*l(k=0,1,2....)
稍微变一下形得:
(n-m)*s+k*l=x-y
令n-m=a,k=b,x-y=c,即
a*s+b*l=c
只要上式存在整数解,则两青蛙能相遇,否则不能。
首先想到的一个方法是用两次for循环来枚举s,l的值,看是否存在s,l的整数解,若存在则输入最小的s,
但显然这种方法是不可取的,谁也不知道最小的s是多大,如果最小的s很大的话,超时是明显的。
其实这题用欧几里德扩展原理可以很快的解决,先来看下什么是欧几里德扩展原理:
欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:
定理:gcd(a,b) = gcd(b,a mod b)
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a - kb,因此d|r
因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
欧几里德算法就是根据这个原理来做的,其算法用C++语言描述为:
int Gcd(int a, int b) { if(b == 0) return a; return Gcd(b, a % b); }
当然你也可以写成迭代形式:
int Gcd(int a, int b) { while(b != 0) { int r = b; b = a % b; a = r; } return a; }
本质上都是用的上面那个原理。
补充: 扩展欧几里德算法是用来在已知a, b求解一组x,y使得a*x+b*y=Gcd(a,b)(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。下面是一个使
用C++的实现:
int exGcd(int a, int b, int &x, int &y) { if(b == 0) { x = 1; y = 0; return a; } int r = exGcd(b, a % b, x, y); int t = x; x = y; y = t - a / b * y; return r; }
把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a' = b, b' = a % b 而言,我们求得 x, y使得 a'x + b'y = Gcd(a', b')
由于b' = a % b = a - a / b * b (注:这里的/是程序设计语言中的除法)
那么可以得到:
a'x + b'y = Gcd(a', b') ===> bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===> ay +b(x - a / b*y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y).
求解 x,y的方法的理解
设 a>b。
1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
2,ab<>0 时
设 ax1+by1=gcd(a,b);
bx2+(a mod b)y2=gcd(b,a mod b);
根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);
则:ax1+by1=bx2+(a mod b)y2;
即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;
根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以
结束。
在网上看了很多关于不定方程方程求解的问题,可都没有说全,都只说了一部分,看了好多之后才真正弄清楚不定方程的求解全过程,步骤如下:
求a * x + b * y = c的整数解。
1、先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a' * x + b' * y = c',此时Gcd(a',b')=1;
2、利用上面所说的欧几里德算法求出方程a' * x + b' * y = 1的一组整数解x0,y0,则c' * x0,c' * y0是方程a' * x + b' * y = c'的一组整数解;
3、根据数论中的相关定理,可得方程a' * x + b' * y = c'的所有整数解为:
其实我们求得的解只是一组,
a*x0+lcm(a,b)+b*y0-lcm(a,b)=1;
a*x +b*y =1;
x=x0+b/gcd(a,b);y=y0-a/gcd(a,b);
a/gcd(a,b)*x'+b/gcd(a,b)*y'=c/gcd(a,b);
x'=c/gcd(a,b)*x0+b/gcd(a,b);y'=c/gcd(a,b)*y0-a/gcd(a,b);
x = c' * x0 + b' * t y = c' * y0 - a' * t (t为整数)
上面的解也就是a * x + b * y = n 的全部整数解
欧几里德算法gcd及其拓展终极解释的更多相关文章
- 欧几里德算法 GCD
递归: int gcd(int a,int b) { ?a:gcd(b,a%b); } 非递归: int gcd(int m,int n) { int r; ) { m=n; n=r; } retur ...
- POJ 1061青蛙的约会(拓展欧几里德算法)
题目链接: 传送门 青蛙的约会 Time Limit: 1000MS Memory Limit: 65536K Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见 ...
- Sicily1099-Packing Passengers-拓展欧几里德算法
最终代码地址:https://github.com/laiy/Datastructure-Algorithm/blob/master/sicily/1099.c 做这题的时候查了别人的做法花了半天都没 ...
- POJ 2773 Happy 2006(欧几里德算法)
题意:给出一个数m,让我们找到第k个与m互质的数. 方法:这题有两种方法,一种是欧拉函数+容斥原理,但代码量较大,另一种办法是欧几里德算法,比较容易理解,但是效率很低. 我这里使用欧几里德算法,欧几里 ...
- (扩展欧几里德算法)zzuoj 10402: C.机器人
10402: C.机器人 Description Dr. Kong 设计的机器人卡尔非常活泼,既能原地蹦,又能跳远.由于受软硬件设计所限,机器人卡尔只能定点跳远.若机器人站在(X,Y)位置,它可以原地 ...
- 欧几里德与扩展欧几里德算法 Extended Euclidean algorithm
欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd( ...
- poj2142-The Balance(扩展欧几里德算法)
一,题意: 有两个类型的砝码,质量分别为a,b;现在要求称出质量为d的物品, 要用多少a砝码(x)和多少b砝码(y),使得(x+y)最小.(注意:砝码位置有左右之分). 二,思路: 1,砝码有左右位置 ...
- poj2115-C Looooops(扩展欧几里德算法)
本题和poj1061青蛙问题同属一类,都运用到扩展欧几里德算法,可以参考poj1061,解题思路步骤基本都一样.一,题意: 对于for(i=A ; i!=B ;i+=C)循环语句,问在k位存储系统中循 ...
- poj1061-青蛙的约会(扩展欧几里德算法)
一,题意: 两个青蛙在赤道上跳跃,走环路.起始位置分别为x,y. 每次跳跃距离分别为m,n.赤道长度为L.两青蛙跳跃方向与次数相同的情况下, 问两青蛙是否有方法跳跃到同一点.输出最少跳跃次数.二,思路 ...
随机推荐
- Android Json数据解析
1.通过主Activity的Button按钮进行解析 public class MainActivity extends Activity { private Button button=null; ...
- 差别不在英语水平,而在汉语水平If you do not leave me, we will die together.
为什么高考语文要提高到180分,英语降到100,差别不在英语水平,而在汉语水平.看下面例句的译法: If you do not leave me, we will die together. 你如果不 ...
- [Sequence Alignment Methods] Cross-Recurrent Plot (CRP)
A recurrence plot (RP) is a straightforward way to visualize characteristics of similar system state ...
- UVALive 7148 LRIP 14年上海区域赛K题 树分治
题意 n个点组成一棵树, 带有点权. 求最长不降的路径的长度, 且路径上最大值最小值之差不超过D. 显然是树分治, 但是分治之后如何维护答案呢. 假设当前重心为g, 分别记录g出发不降路径的长度,以及 ...
- RabbitMQ-清空队列中(一个channel或连接中)的Unacknowledged状态的消息
清空所有:nack 时将参数delivery-tag设为0,multiple设为1. 清空小于等于某delivery-tag的所有消息:nack 时将参数delivery-tag设为正数(介于1和92 ...
- Python监控日志程序
一个简易的日志监控的脚本,功能如下:1.windows环境2.当匹配日志关键字时会发出声音,匹配的关键字不同,播放的声音不同3.能做到实时响应 注意:是在win环境下哦 直接上代码吧 1 2 3 4 ...
- GS1已分配给国家(地区)编码组织的前缀码
前缀码即商品条码(EAN-13或者EAN-8)的前三位,其代表的是一个国家和地区,由此前缀可查出所购买的商品是出产自哪个国家的. 下表列出了GS1已分配给国家(地区)编码组织的前缀码 前缀码 管理的国 ...
- Android Scroller类的详细分析
尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/7321910 Scroller这个类理解起来有一定的困难,刚开始接触Scrol ...
- java參数传递机制浅析
欢迎转载,转载请声明出处! ----------------------------------------- 前言: java语言中,參数的传递仅仅有一种机制.那就是值传递. 举例: 以下将通过几个 ...
- VB.NET版机房收费系统—DataGridView应用
事实上,先前刚刚開始敲机房的时候,刚用到DataGridView的时候,总显得力不从心,先要一下子就学会,看了非常多的资料,但是依照写的时候,自己有不知道从什么地方下手,于是,当自己用查询SQL语句, ...