欧几里得算法与扩展欧几里得算法

欧几里得算法基于这样一个 GCD 递归定理:

$gcd(a, b) = gcd(b, a\bmod{b}) $

证明如下:

假设 $a > b$, $a = kb + r(0 <= r < b)$, 即 $a\bmod{b} = r$.

若有 $d \mid a$ 且 $d \mid b$, 必然有 $d \mid a - kb$, 即 $d \mid r$. 由此得知, $a$ 与 $b$ 的所有公约数必然是 $b$ 与 $r$ 的公约数.

若有 $d \mid r$ 且 $d \mid b$, 必然有 $d \mid kb + r$, 即 $d \mid a$. 由此得知, $b$ 与 $r$ 的所有公约数必然是 $a$ 与 $b$ 的公约数.

所以 $gcd(a, b) = gcd(b, r)$, 即 $gcd(a, b) = gcd(b, a\bmod{b})$

然后, 通过不断递归直到 $b = 0$, 再不断返回就能求出 $gcd(a, b)$.

int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}

扩展欧几里得算法利用了欧几里得算法的一些有用信息, 从而求出同余模方程 $ax + by = gcd(a, b)$ 的一组解. 通过数学归纳法可以证明扩展欧几里得算法的正确性.

1. 当 $b = 0$ 时, $gcd(a, b) = a$, 显然 $x = 1, y = 0$ 是一组合法的解

2. 当 $b > 0$ 时, 假设我们已经求得了方程 $bx + (a\bmod{b})y = gcd(b, a\bmod{b})$ 的一组解 $(x_0, y_0$), 同时设 $(x_1, y_1)$ 是方程 $ax + by = gcd(a, b)$ 的一组解, 那么有

$ax_1 + by_1 = bx_0 + (a\bmod{b})y_0$

$ax_1 + by_1 = bx_1 + (a - \frac{a}{b}\cdot b)y_1$

$ax_1 + by_1 = b(x_0-\frac{a}{b}\cdot y_0) + ay_0$

对应相等, 我们可以得到

$x_1 = y_0$

$y_1 = x_0 - \frac{a}{b}\cdot y_0$

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 -= (a / b) * x;
    }
}

(上述代码运用了一点小技巧: 让 $x$ 与 $y$ 在递归调用时错位以减少代码量, 整理一下对应关系就能发现其正确性.)

运用欧几里得算法得到方程 $ax + by = gcd(a, b)$ 的一组解 $(x_1, y_1)$ 后, 假设该方程的另一组解为 $(x_2, y_2)$, 那么有

$ax_1 + by_1 = ax_2 + by_2$

整理得

$a(x_1-x_2) = b(y_2-y_1)$

两边同除以 $g=gcd(a, b)$, 得

$a‘(x_1-x_2) = b‘(y_2-y_1)$

因为 $a‘$ 与 $b‘$ 互质, 所以 $b‘ \mid (x_1-x_2)$, 则可设 $x_1-x_2 = kb‘$, 那么有

$a‘k = y_2-y_1$

即 $y_2 = y_1+ka‘$

同时也得到了 $x_2 = x_1+kb‘$

由上, 得到一组解 $(x_1, y_1)$ 后, 就得到另一组解 $x_2 = x_1+kb‘, y_2 = y_1+ka‘$.

由扩展欧几里得算法, 我们就可以解出一般的不定方程 $ax + by = c$ 的解:

若 $\gcd(a, b)  \mid  c$ , 则方程有解. 假设 $(x_0, y_0)$ 是方程 $ax + by = gcd(a, b)$ 的一组解, 那么我们可以得到方程 $ax + by = c$ 的一组解 $(\frac{c}{gcd(a,b)}\cdot{x_0}, \frac{c}{gcd(a,b)}\cdot{y_0})$;

否则, 方程无整数解.

另外, 我们还可以用扩展欧几里得算法来解线性同余模方程组. 比如:

$x\equiv m_1\pmod{a_1}$

$x\equiv m_2\pmod{a_2}$

...

$x\equiv m_n\pmod{a_n}$

我们可以将其两两合并. 比如对于前两个方程, 假设 $m_1y+a_1=x$, $m_2z+a_2=x$, 则

$m_1y-m_2z=a_2-a_1$

这是一个一般的不定方程, 用扩展欧几里得算法得到一个 $y_0$ 值, 我们就可以计算出一个可行的 $x_0$ 值, 那么显然 x 的一般解就是

$x = x_0 + t[m_1, m_2]$

由这个等式我们又可以构造出一个新的方程:

$x\equiv x_0\pmod{[m_1, m_2]}$

再将这个方程与第三个方程联立, 得到新的方程. 重复此过程即可得到该方程组的一个解.

时间: 2024-11-08 19:53:28

欧几里得算法与扩展欧几里得算法的相关文章

欧几里得算法与扩展欧几里得算法_C++

先感谢参考文献:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 注:以下讨论的数均为整数 一.欧几里得算法(重点是证明,对后续知识有用) 欧几里得算法,也叫辗转相除,简称 gcd,用于计算两个整数的最大公约数 定义 gcd(a,b) 为整数 a 与 b 的最大公约数 引理:gcd(a,b)=gcd(b,a%b) 证明: 设 r=a%b , c=gcd(a,b) 则 a=xc , b=yc , 其中x , y互质

欧几里得算法以及扩展欧几里得算法(过河noip2005提高组第二题)

欧几里得算法:也被称作辗转相除法 gcd(a,b)=gcd(b,a%b); 终止条件a=gcd b=0; (gcd为a,b的最大公约数) 扩展欧几里得算法: a 和 b 的最大公约数是 gcd ,一定能够找到这样的 x 和 y ,使得: a*x + b*y = gcd 成立 我们只需要找到特殊解x0,y0; 则通解为 x = x0 + (b/gcd)*t    y = y0 – (a/gcd)*t 那如何求出下一组解呢 仿照欧几里得算法a=b,b=a%b代入. a%b = a - (a/b)*b

扩展欧几里得算法的模板实现

我居然现在还记不住扩欧的板子,我太弱啦! 扩展欧几里得算法解决的是这样的问题: 给定一个不定方程组ax+by=gcd(a,b),求他的一组整数解 先给出实现代码 void exgcd(int a,int b,int &x,int &y) { if(!b) { x=1,y=0;//gcd(a,0)显然等于1*a-0*0=a return a; } int ans=exgcd(b,a%b,x,y); int tem=x; x=y; y-=tem-(a/b)*y; return ans;} 但实

POJ - 1061 青蛙的约会 (扩展欧几里得算法)

Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的.但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的.为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面. 我们把这

[NOI2002] 荒岛野人 扩展欧几里得算法

[问题描述] 克里特岛以野人群居而著称.岛上有排列成环行的M个山洞.这些山洞顺时针编号为1,2,-,M.岛上住着N个野人,一开始依次住在山洞 C1,C2,-,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来.每个野人i有一个寿命值Li,即生存的年数.下面四幅图描述了一个有6个 山洞,住有三个野人的岛上前四年的情况.三个野人初始的洞穴编号依次为1,2,3:每年要走过的洞穴数依次为3,7,2:寿命值依次为4,3,1.     奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个

扩展欧几里得算法(extgcd)

相信大家对欧几里得算法,即辗转相除法不陌生吧. 代码如下: int gcd(int a, int b){ return !b ? gcd(b, a % b) : a; } 而扩展欧几里得算法,顾名思义就是对欧几里得算法的扩展. 切入正题: 首先我们来看一个问题: 求整数x, y使得ax + by = 1, 如果gcd(a, b) != 1, 我们很容易发现原方程是无解的.则方程ax + by = 1有正整数对解(x, y)的必要条件是gcd(a, b) = 1,即a, b 互质. 此时正整数对解

扩展欧几里得算法学习记

话说以前我刷noip题的时候就想学这个东西了,结果却一直拖到了现在…… 到了高二才会这种东西的我实在是个蒟蒻啊! 将扩展欧几里得算法之前,先讲讲欧几里得算法是什么:gcd(a,b)=gcd(b,a%b).很显然是不?但我们还是要给出证明(设r=a%b): 设x是a,b的一个公约数,由于存在k使得a=k*b+r,又由于a|x,b|x,则有r|x,所以x是b,r的公约数 设x是b,r的一个公约数,因为存在k使得a=k*b+r,且b|x,r|x,那么a|x,所以x是a,b的公约数 综上所述,a和b的所

欧几里得算法与扩展算法相关内容

推荐博客     http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 欧几里得算法求最大公约数(辗转相除) 定理 gcd( m , n )=gcd ( n , m mod n ) ( m>n 且 m mod n 不为0) 最小公倍数记为lcm( m , n ),显然lcm( m , n )=m*n / gcd( m , n ) 对于正整数k,有性质 lcm( km , kn)=k*gcd( m , n ) 欧几里得算

HDU - 1576 A/B(扩展欧几里得算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576 题意:要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). 普通版欧几里得算法(辗转相除): 1 typedef long long LL; 2 LL gcd(LL a,LL b){ 3 return (b==0) ? a : gcd(b,a%b); 4 } 扩展欧几里得算法(理论):对于不完全为0的非负整数,