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

欧几里得算法:最大公因数\((gcd)\)

该算法基于:

\(gcd(a,b)=gcd(b,a\)%\(b)\)

证明:

令\(a\) % \(b = r\),

则 \(a = k * b + r,\)

因此\(r = a - k * b\)

设\(d\)为\(a,b\)的公约数,那么\(d|a, d|b,\)

则\(a - k * b\) 能被\(d\)整除,即\(d|r\),即\(d|(a\) % \(b)\),

因此\(d\)是\(b\) 和 \((a\) %\(b)\)的公约数,

因此\(a,b\) 的公约数和\(b, (a\)%\(b)\)的公约数是同一个数,

得出\(gcd(a,b)=gcd(b,a\)%\(b)\)

同时知道\(gcd(a,0)=a\)

因此递归求解即可:

inline int gcd(int a,int b)
{
    if (b==0) return a;
    return gcd(b,a%b);
}

对于这个简单的gcd,背结论不求甚解我觉得是可以dei


扩展欧几里得算法\((exgcd)\)

对于一类形如\(ax+by=gcd(a,b)\)的方程求解其x,y的一组解:

通过辗转法,可得\(bx+y(a\)%\(b)=gcd(b,a\)%\(b)\)

用除法代替取模,则:\(bx+y(a-[a/b]*b)=gcd(b,a\)%\(b)\)(这一步仅仅是原方程的变形)

根据上述欧几里得算法可得,\(gcd(a,b)=gcd(b,a\)%\(b)\)

因此\(ax+by=bx‘+y‘(a-[a/b]*b)\)

通过乘法分配律和结合律的运算可得:\[ax+by=ay‘+b(x‘-[a/b]*y‘)\]

其中,\(x‘\)和\(y‘\)是方程\(bx+y(a-[a/b]*b)=gcd(b,a\%b)\)的解,用来借助这个已经求得的x‘和y‘结合已知的a和b推得现在的解\(x,y.\)其中\(a\)和\(b\)不变。我们可以通过递归来求。

递归的边界:

\(ax+by=gcd(a,0)\)时,即\(b=0\)时,\(x=1\ y=0\).显而易见。

故代码很好理解了吧:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int x,y;
int exgcd(int a,int b)
{
    if (b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int n=exgcd(b,a%b);
    int t=x;
    x=y;
    y=t-a/b*y;
    return n;
}
int main(void)
{
    int a,b;
    cin>>a>>b;
    cout<<exgcd(a,b)<<endl;//这里输出最大公约数
    cout<<x<<‘ ‘<<y<<endl;//这个输出方程ax+by=gcd(a,b)的解
    return 0;
}

<\font>

原文地址:https://www.cnblogs.com/pigzhouyb/p/10119692.html

时间: 2024-10-07 05:27:36

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

欧几里得 &amp; 拓展欧几里得算法 讲解 (Euclid &amp; Extend- Euclid Algorithm)

欧几里得& 拓展欧几里得(Euclid & Extend-Euclid) 欧几里得算法(Euclid) 背景: 欧几里德算法又称辗转相除法,用于计算两个正整数a,b的最大公约数.                                                                                                                                               --百度百科 代码: 递推的代

扩展欧几里得算法+推论

什么是扩展欧几里得? 扩展欧几里得算法是建立在欧几里得算法(gcd)之上. 首先,我们知道有\(a*x+b*y=gcd(a,b)\) 我们怎么求这个\(x,y\)呢? 这时候我们就得使用exgcd算法,我们来推导一下吧! \(a*x+b*y=gcd(a,b)\) \(a*x+b*y=gcd(b,a\% b)\) \(a*x+b*y=b*x'+(a- \left \lfloor \frac{a}{b} \right \rfloor*b)*y'\) \(a*x+b*y= a*y'+b*(x'-\le

欧几里得&amp;扩展欧几里得算法

朴素的欧几里得算法大家应该知道 \(gcd(a,b)\)表示a,b的最大公约数 朴素的欧几里得算法其实就是所谓的辗转相除法 辗转相除法 \(gcd(a,b)=gcd(b,a\) \(mod\) \(b)\) 证明如下: \(设r=a\) \(mod\) \(b\) \(=a-\lfloor\frac{a}{b}\rfloor*b\),\(p=gcd(a,b)\); 则\[a=xp,b=yp\] 代入可得\[r=xp-\lfloor\frac{xp}{yp}\rfloor*yp\] 提公因式得\[

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

我居然现在还记不住扩欧的板子,我太弱啦! 扩展欧几里得算法解决的是这样的问题: 给定一个不定方程组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 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的.但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的.为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面. 我们把这

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的非负整数,

【hdu1576】A/B——扩展欧几里得算法

扩展欧几里得的模板题,要记住: x=y1; y=x1-a/b*y1. 这道题的推导过程如下: 1.因为A/B==0,所以令A/B=x,即A=Bx.又因为n=A%m,所以m*y+n=A. 由上面可推导出Bx-my=n. 2.由扩展欧几里得算法可以算出B*x1+m*y1=1的根,等式两边同时乘上n可以变形为B*(x1*n)-m*(-n*y1)=n. 所以x=n*x1.到这里我们只需要通过扩欧算出x1,答案即为(x1*n)%m. 3.最后要注意的一点,扩展欧几里得算法算出的x1可能为负数,这显然是不成

欧几里得及扩展欧几里得

欧几里得算法又称辗转相除法,主要用于求两数的最大公约数即gcd(a,b). 欧几里得算法给出gcd(a,b)=gcd(b,a%b)(a>b) 下面我们给出证明: 首先我们设k为gcd(a,b),则a=km,b=kn. 则a%b=a-c*b=km-c*kn=(m-cn)k gcd(b,a%b)=gcd(kn,(m-cn)k) 由于k为a,b的最大公约数,所以n与m-cn互质,所以gcd(b,a%b)=gcd(a,b)=k. 程序实现: 1 int gcd(int a,int b) 2 { 3 if

扩展欧几里得算法求解不定方程【例 poj 1061】

扩展欧几里得算法是数论当中一种常用的算法,他可以用如下的姿势来表达: 设a, b为不全为0的整数,则存在整数x和y,使得 gcd(a, b) = a*x + b*y. 证明就略去. 树上还有一个拉梅定理:用欧几里得算法计算两个正整数的最大公因子时,所需要的除法次数不会超过两个整数中较小的那个十进制数的倍数的5倍. 拉梅定理的一个推论:求两个正整数a, b, a > b的最大公因子需要O(log2a)3次的位运算. 至于拉梅定理有什么用,暂时还没有研究=—=. 例1 求225和21的最大公因子s,