『扩展欧几里得算法 Extended Euclid』
<更新提示>
<第一次更新>
<正文>
Euclid算法(gcd)
在学习扩展欧几里得算法之前,当然要复习一下欧几里得算法啦。
众所周知,欧几里得算法又称gcd算法,辗转相除法,可以在\(O(log_2b)\)时间内求解\((a,b)\)(a,b的最大公约数)。
其核心内容可以陈述为:\((a,b)=(b,a\%b)\),然后反复迭代该式缩小\(a,b\)规模,直到\(b=0\),得到a为最大公约数。
证明
设两数为\(a\ b(b<a)\),求它们最大公约数的步骤如下:用\(b\)除\(a\),即\(a/b=q…..r\),得\(a=bq+r(0≤r<b)\),即为余数,\(q\)是这个除法的商)。若\(r=0\),则\(b\)是\(a\)和\(b\)的最大公约数,\(a\),\(b\)存在倍数关系。若\(r≠0\),则继续考虑。
首先,应该明白的一点是任何 \(a\) 和 \(b\) 的公约数都是 \(r\) 的公约数。要想证明这一点,就要考虑把 \(r\) 写成 \(r=a-bq\)。现在,如果 \(a\) 和 \(b\) 有一个公约数 \(d\),而且设 \(a=sd , b=td\), 那么 \(r = sd-tdq = (s-tq)d\)。因为这个式子中,所有的数(包括 \(s-tq\))都为整数,所以 \(r\) 可以被 \(d\) 整除。
对于所有的 \(d\) 的值,这都是正确的。所以 \(a\) 和 \(b\) 的最大公约数也是 \(b\)(因为\(b< a\),所有取b继续运算才能不断缩小规模,直至两数有倍数关系) 和 \(r\) 的最大公约数。因此我们可以继续对 \(b\) 和 \(r\) 进行上述取余的运算。这个过程在有限的重复后,可以最终得到 \(r=0\) 的结果,我们也就得到了 \(a\) 和 \(b\) 的最大公约数
实现
\(Code:\)
inline int Euclid(int a,int b){return b==0?a:Eucild(b,a%b);}
Extended Euclid算法(exgcd)
那么接下来就是扩展欧几里得啦。
正如其名,扩展欧几里得算法就是基于欧几里得算法的扩展运用。该算法用于解决一下模型的问题:
求解关于\(x,y\)的二元不定方程\(ax+by=c\)的整数解
在讲解算法之前,需要先了解该算法的核心,即裴蜀定理:
对任何整数\(a,b\),关于未知数x和y的线性丢番图方程(称为裴蜀等式):\(ax+by=c\),方程有整数解当且仅当\(c\)是\((a,b)\)的倍数。裴蜀等式有解时必然有无穷多个解。
证明
1.必要性证明:如果有整数解,则\(c\)是\(p\)的倍数
令\(p=(a,b)\),设\(a=a'p\),\(b=b'p\),则有\((a',b')=1\)成立。那么
\\⇒a'px+b'py=c
\\⇒p(a'x+b'y)=c
\]
那么\(c\)就是\(p\)的一个因数,所以\(p|c\)得证。
2.充分性证明:如果\(c\)是\(p\)的倍数,则\(ax+by=c\)有整数解
令\(p=(a,b)\),记欧几里得算法中每一次辗转得到的数对为\((a_1,b_1),(a_2,b_2),...,(a_n,b_n)\),其中,\((a_1,b_1)\)即为\((a,b)\),\((a_n,b_n)\)即为\((p,0)\),符合辗转相除法的流程。
对于\((a_n,b_n)\),求方程\(a_nx+b_ny=c\)的解,由于\(a_n=p,b_n=0\),我们可以构造一组解:
x_n=\frac{c}{p}
\\∀y_n\in Z
\end{cases}
\]
适用于\((a_n,b_n)\),且\((x_n,y_n)\)一定为整数(因为\(p|c\),\(y_n\)取任意整数)。
至此,数学归纳法的底基证明完毕。
由于辗转相除法,我们可以得知
\\b_n=a_{n-1}\%b_{n-1}
\\⇒b_n=a_{n-1}-\lfloor a_{n-1}/b_{n-1}\rfloor b_{n-1}\ ②
\]
我们刚才已经推得:\(a_nx+b_ny=c\)的一组整数解\((x_n,y_n)\),那么可以把\(①②\)两式代入\(a_nx+b_ny=c\)得:
\]
且对于该方程,解\((x_n,y_n)\)仍适用,即:
\]
成立,可以进行推导:
\\⇒b_{n-1}x_n+a_{n-1}y_n-\lfloor a_{n-1}/b_{n-1}\rfloor b_{n-1} y_n=c
\\⇒a_{n-1}y_n+b_{n-1}(x_n-\lfloor a_{n-1}/b_{n-1}\rfloor y_n)=c\ ③
\]
注意到两项的系数分别为\(a_{n-1},b_{n-1}\),所以对于方程\(a_{n-1}x+b_{n-1}y=c\),通过③式可以直接得到一组解:
x_{n-1}=y_n
\\y_{n-1}=x_n-\lfloor a_{n-1}/b_{n-1}\rfloor y_n
\end{cases}
\]
由此,我们利用辗转相除法的关系,通过方程\(a_nx+b_ny=c\)的一组解\((x_n,y_n)\),推得了方程\(a_{n-1}x+b_{n-1}y=c\)的一组解\((x_{n-1},y_{n-1})\)。
同样地,我们可以由\((x_i,y_i)\)的一组解,得到方程\(a_{i-1}x+b_{i-1}y=c\)的一组解\((x_{i-1},y_{i-1})\)
x_{i-1}=y_i
\\y_{i-1}=x_i-\lfloor a_{i-1}/b_{i-1}\rfloor y_i
\end{cases}
\]
由上,数学归纳法完成证明:如果我们得知\(a_nx+b_ny=c\)的一组解\((x_n,y_n)\),且\((a_1,b_1),(a_2,b_2),...,(a_n,b_n)\)是由辗转相除法得到的序列,那么我们就可以通过以上方法得到原方程\(a_1x+b_1y=c\)的解\((x_1,y_1)\)。
然而,我们已经通过构造法得到\(a_nx+b_ny=c\)的一组解\((x_n,y_n)\),且保证c是p的倍数时,整数解\((x_n,y_n)\)一定存在。故c是p的倍数时,方程\(ax+by=c\)一定有整数解。充分性得证。
实现
回归正题,看扩展欧几里得算法。
千万不要想着不看证明咯。裴蜀定理的充分性证明过程就是扩展欧几里得算法的流程。
先由辗转相除法求解\((a,b)\),得到\(p=(a,b)\)
同时,构造解\((x_n,y_n)\)
x_n=\frac{c}{p}
\\∀y_n\in Z
\end{cases}
\]
在递归的回溯过程中,利用公式:
x_{i-1}=y_i
\\y_{i-1}=x_i-\lfloor a_{i-1}/b_{i-1}\rfloor y_i
\end{cases}
\]
倒推每一组\((a_i,b_i)\)的解\((x_i,y_i)\)。
最后得到\((a,b)\)和原方程\(ax+by=c\)的一组解\((x,y)\)。
至此,扩展欧几里得算法完成。
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
inline int Extended_Euclid(int a,int &x,int b,int &y,int c)
{
if(b==0){x=c/a,y=0;return a;}
else
{
int p=Extended_Euclid(b,x,a%b,y,c);
int x_=x,y_=y;
x=y_; y=x_-a/b*y_;
return p;
}
}
int main(void)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int p,x,y;
p=Extended_Euclid(a,x,b,y,c);
printf("(%d,%d)=%d\n",a,b,p);
printf("x=%d,y=%d\n",x,y);
}
<后记>
『扩展欧几里得算法 Extended Euclid』的更多相关文章
- 扩展欧几里得算法(extgcd)
相信大家对欧几里得算法,即辗转相除法不陌生吧. 代码如下: int gcd(int a, int b){ return !b ? gcd(b, a % b) : a; } 而扩展欧几里得算法,顾名思义 ...
- noip知识点总结之--欧几里得算法和扩展欧几里得算法
一.欧几里得算法 名字非常高大上的不一定难,比如欧几里得算法...其实就是求两个正整数a, b的最大公约数(即gcd),亦称辗转相除法 需要先知道一个定理: gcd(a, b) = gcd(b, a ...
- 欧几里得算法与扩展欧几里得算法_C++
先感谢参考文献:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 注:以下讨论的数均为整数 一.欧几里得算法(重点是证 ...
- vijos1009:扩展欧几里得算法
1009:数论 扩展欧几里得算法 其实自己对扩展欧几里得算法一直很不熟悉...应该是因为之前不太理解的缘故吧这次再次思考,回看了某位大神的推导以及某位大神的模板应该算是有所领悟了 首先根据题意:L1= ...
- ****ural 1141. RSA Attack(RSA加密,扩展欧几里得算法)
1141. RSA Attack Time limit: 1.0 secondMemory limit: 64 MB The RSA problem is the following: given a ...
- 浅谈扩展欧几里得算法(exgcd)
在讲解扩展欧几里得之前我们先回顾下辗转相除法: \(gcd(a,b)=gcd(b,a\%b)\)当a%b==0的时候b即为所求最大公约数 好了切入正题: 简单地来说exgcd函数求解的是\(ax+by ...
- (light oj 1306) Solutions to an Equation 扩展欧几里得算法
题目链接:http://lightoj.com/volume_showproblem.php?problem=1306 You have to find the number of solutions ...
- 题解——洛谷P2613 【模板】有理数取余(扩展欧几里得算法+逆元)
题面 题目描述 给出一个有理数 c=\frac{a}{b} ,求 c mod19260817 的值. 输入输出格式 输入格式: 一共两行. 第一行,一个整数 \( a \) .第二行,一个整 ...
- 【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元
有这样的问题: 给你两个整数数$(a,b)$,问你整数$x$和$y$分别取多少时,有$ax+by=gcd(x,y)$,其中$gcd(x,y)$表示$x$和$y$的最大公约数. 数据范围$a,b≤10^ ...
随机推荐
- 有意思的算法题:有10个文件,每个文件大概有10G,求里面最大的100个数;
算法思路 1: 第一个阶段:对于单个10G文件而言 1. 初始化:先取100个数,构建最小堆: 开始比较: 2. 取一个数 A,与最小堆的根节点进行比较: 3. 如果 A > 最小堆根节点,则替 ...
- java并发编程可见性与线程封闭
可见性 所谓可见性,指的是当一个线程修改了对象的状态后,其他线程能够看到该对象发生的变化.在单线程环境下,向某个变量写入值,然后在后面的操作再读取,在这个过程中该变量的值对该线程来说总是可见.但是,在 ...
- SQL注入——知表名不知列明情景下查询数据
场景 有某些情况,可以查找到表名,但查找不到列名. MySQL < 5 或 web过滤 information_scema 详解 select `1` from (select 1,2,3,4, ...
- SI9000常用共面阻抗模型的解释
所谓的“共面”,即阻抗线和参考层在同一平面,即阻抗线被VCC/GND所包围, 周围的VCC/GND即为参考层. 相较于单端和差分阻抗模型,共面阻抗模型多了一个参数D1,即阻抗线和参 考层VCC/GND ...
- Linux内核内存管理架构
内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射.页面分配.页面回收.页面交换.冷热页面.紧急页面.页面碎片管理.页面缓存.页面统计等,而且对性能也有很高的要 ...
- ios 上下滑动粘滞问题
ios 移动端,当你触及到可以左右滑动部分,进行上下滑动操作时,会导致上下滑动粘滞卡顿的问题 mdn:https://developer.mozilla.org/zh-CN/docs/Web/CSS/ ...
- [ubuntu]apt-get update突然出现arm package找不到
https://blog.csdn.net/l741299292/article/details/69671789
- go语言数据库操作, gorm框架
type User struct{ ID uint `gorm:"primary_key"` Name string Age int Birthday time.Time AddT ...
- ORACLE启动报错ORA-03113: end-of-file on communication channel
使用过程中发现oracle运行很慢(其实应该先关注空间问题),就准备关机重启一下,关不掉就强制关闭,然后启动就报错了. 1.SQL> startup ORACLE instance starte ...
- javascript函数传值问题(传值?址)
通常对于我们开发者来说,有不少人是忽略了这些小问题的,但是我们又必要去了解.因为今天一个朋友问起,所以写到这里来了, 在C#中,我们知道如果要往一个函数中传递参数的类型为对象,数组或者其他引用类型时. ...