欧几里得算法与扩展欧几里得算法_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互质

    r=a%b=a-pb=xc-pyc=(x-py)c

    而b=yc

    可知:y 与 x-py 互质

    证明:

  假设 y 与 x-py 不互质

  设 y=nk , x-py=mk , 且 k>1 (因为互质)

   将 y 带入可得

  x-pnk=mk

  x=(pn+m)k

   则 a=xc=(pn+m)kc , b=yc=nkc

  那么此时 a 与 b 的最大公约数为 kc 不为 k

  与原命题矛盾,则 y 与 x-py 互质

    因为 y 与 x-py 互质,所以 r 与 b 的最大公约数为 c

    即 gcd(b,r)=c=gcd(a,b)

    得证

  当a%b=0时,gcd(a,b)=b

  这样我们可以写成递归形式

1 inline int gcd(int a,int b)
2 {
3     return b?gcd(b,a%b):a;
4 }

  模板题:http://codevs.cn/problem/1212/

二、扩展欧几里得算法

  扩展欧几里得算法,简称 exgcd,一般用来求解不定方程,求解线性同余方程,求解模的逆元等

  引理:存在 x , y 使得 gcd(a,b)=ax+by

  证明:

  当 b=0 时,gcd(a,b)=a,此时 x=1 , y=0

  当 b!=0 时,

         设 ax1+by1=gcd(a,b)=gcd(b,a%b)=bx2+(a%b)y2

  又因 a%b=a-a/b*b

  则 ax1+by1=bx2+(a-a/b*b)y2

    ax1+by1=bx2+ay2-a/b*by2

    ax1+by1=ay2+bx2-b*a/b*y2

    ax1+by1=ay2+b(x2-a/b*y2)

    解得 x1=y2 , y1=x2-a/b*y2

    因为当 b=0 时存在 x , y 为最后一组解

    而每一组的解可根据后一组得到

    所以第一组的解 x , y 必然存在

    得证

  根据上面的证明,在实现的时候采用递归做法

  先递归进入下一层,等到到达最后一层即 b=0 时就返回x=1 , y=0

  再根据 x=y’ , y=x’-a/b/y’ ( x’ 与 y’ 为下一层的 x 与 y ) 得到当层的解

  不断算出当层的解并返回,最终返回至第一层,得到原解

 1 inline void exgcd(int a,int b)
 2 {
 3     if (b)
 4         {
 5             exgcd(b,a%b);
 6             int k=x;
 7             x=y;
 8             y=k-a/b*y;
 9         }
10     else y=(x=1)-1;
11 }

三、exgcd 解不定方程(使用不将a与b转为互质的方法)

  对于 ax+by=c 的不定方程,设 r=gcd(a,b)

  当 c%r!=0 时无整数解

  当 c%r=0 时,将方程右边 *r/c 后转换为 ax+by=r 的形式

  可以根据扩展欧几里得算法求得一组整数解 x0 , y0

  而这只是转换后的方程的解,原方程的一组解应再 *c/r 转变回去

  (如 2x+4y=4 转换为 2x+4y=2 后应再将解得的 x , y 乘上2)

  则原方程解为 x1=x0*c/r , y1=x0*c/r

  通解 x=x1+b/r*t , y=y1-a/r*t ,其中 t 为整数

  证明:

    将 x , y 带入方程得

    ax+ab/r*t+by-ab/r*t=c

    ax+by=c

    此等式恒成立

    得证

  这里 b/r 与 a/r 为最小的系数,所以求得的解是最多最全面的

  证明:

    为了推出证明中的 ax+by=c ,且想达到更小的系数,只能将 b/r 与 a/r 同除以一个数 s

    而 b/r 与 a/r 互质,且 s 为整数,则 s=1 ,不影响通解

    那么 b/r 与 a/r 就为最小的系数

    得证

  模板题:http://www.cnblogs.com/hadilo/p/5917173.html

  (此处仍需补充一道模板题,有建议者联系作者

   联系方式:http://www.cnblogs.com/hadilo/p/5932395.html

四、exgcd 解线性同余方程

  关于 x 的模方程 ax%b=c 的解

  方程转换为 ax+by=c 其中 y 一般为非正整数

  则问题变为用 exgcd 解不定方程

  解得 x1=x0*c/r

  通解为 x=x1+b/r*t

  设 s=b/r (已证明 b/r 为通解的最小间隔)

  则 x 的最小正整数解为 (x1%s+s)%s

  证明:

    若 x1>0,则 (x1%s+s)%s=x1%s%s+s%s=x1%s=x1-ts (t∈N)

    若 x1<0,因在 C++ 里 a%b=-(-a%b)<0 (a<0 , b>0)  如 -10%4=-2

         则 (x1%s+s)%s=(-(-x1%s)+s)%s=(-(ts-x1)+s)%s=ts-x1 (t∈N)

    即为 x1 通过加或减上若干个 s 后得到的最小正整数解

    得证

  亦可伪证 x1<0 的情况:设 x1=-5 , s=2

              则 (x1%s+s)%s=(-5%2+2)%2=(-1+2)%2=3%2=1

              即为 x1 加上 3 个 s 后的到的最小正整数解

  模板题:http://www.cnblogs.com/hadilo/p/5951091.html

  (未完待续)

五、excgd 求模的逆元

  (在此处开始编辑)

  最新更新截止时间:2016-10-11 22:52:11

版权所有,转载请联系作者,违者必究

联系方式:http://www.cnblogs.com/hadilo/p/5932395.html

时间: 2024-10-08 09:04:34

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

欧几里得算法以及扩展欧几里得算法(过河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

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

欧几里得算法基于这样一个 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 \mi

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

我居然现在还记不住扩欧的板子,我太弱啦! 扩展欧几里得算法解决的是这样的问题: 给定一个不定方程组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的非负整数,