欧几里得算法和扩展欧几里得算法(Euclidean_Algorithm and Extended_Euclidean_Algorithm)

一、基本概念

欧几里得算法:又名辗转相除法,计算两个整数a,b的最大公约数。

扩展欧几里得算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。

二、基本性质

gcd函数的基本性质:gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)

贝祖定理: 即如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。

三、算法

欧几里得算法

gcd(a,b) = gcd(b,a mod b)

证明:

将a表示为 a=kb+r,则 r=a%b , r=a-kb;

假设d为a,b的一个公约数,则a%d = 0 , b%d = 0  , 又r = a - kb,所以r % d = 0;

整理下:b % d = 0 , r % d = 0( (a % b) % d = 0 )

即 d也是b和a%b的公约数,所以a和b的最大公约数也是b和a%b的最大公约数。

扩展欧几里得算法

已知:a%b=a-(a/b)*b

b*x1 + (a-(a/b)*b)*y1

= b*x1 + a*y1 – (a/b)*b*y1

= a*y1 + b*(x1 – a/b*y1) = gcd

证明:

假设 a>b,

(1)  b=0  gcd(a,b) = a ,  ax = a ,  则x=1,y=0;(这里我还是推荐不把gcd(a,0)理解成最大公约数,而是一个计算机求出来的值)

(2) 假设 ax1+by1=gcd(a,b) (方程一) bx2+(a%b)y2=gcd(b,a%b)(方程二);由欧几里得算法gcd(a,b) =gcd(b,a%b) 得到,

ax1+by1 = bx2+(a%b)y2,即ax1+by1=bx2+(a-a/b*b)y2 ax1+by1=ay2+b(x2-a/b*y2)

四、代码

欧几里得算法

C++版本一

1. 若 r 是 a ÷ b 的余数, 则

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

2. a 和其倍数之最大公因子为 a。

#include<iostream>
using namespace std;

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

int main()
{
    int a,b;
    cout<<"Please enter two integers:"<<endl;
    cin>>a>>b;
    cout<<a<<" and "<<b<<"'s gcd is:"<<endl;
    cout<<gcd(a,b)<<endl;
return 0;
}

C++版本二

1. a ÷ b,令r为所得余数(0≤r<b)

若 r = 0,算法结束;b 即为答案。

2. 互换:置 a←b,b←r,并返回第一步。

#include<iostream>
using namespace std;

int gcd(int a,int b)
{
    int temp;
    while(b!=0)
    {
        temp=b;
        b=a%b;
        a=temp;
    }
    return a;
}

int main()
{
    int a,b;
    cout<<"Please enter two integers:"<<endl;
    cin>>a>>b;
    cout<<a<<" and "<<b<<"'s gcd is:"<<endl;
    cout<<gcd(a,b)<<endl;
return 0;
}

 

扩展欧几里得算法

C++版本一

#include<iostream>
using namespace std;

int exgcd(int a,int b,int &x,int &y)
{
     if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int gcd=exgcd(b,a%b,x,y);
    int x2=x,y2=y;
    x=y2;
    y=x2-(a/b)*y2;
    return gcd;
}

int main()
{
int x,y,a,b;
cout<<"请输入a和b:"<<endl;
cin>>a>>b;
cout<<"a和b的最大公约数:"<<endl;
cout<<exgcd(a,b,x,y)<<endl;
cout<<"ax+by=gcd(a,b) 的一组解是:"<<endl;
cout<<x<<" "<<y<<endl;
return 0;
}

C++版本二

#include<iostream>
using namespace std;

int exgcd(int a,int b,int &x,int &y)
{
    int x1,y1,x0,y0;
    x0=1; y0=0;
    x1=0; y1=1;
    x=0; y=1;
    int r=a%b;
    int q=(a-r)/b;
    while(r)
    {
        x=x0-q*x1; y=y0-q*y1;
        x0=x1; y0=y1;
        x1=x; y1=y;
        a=b; b=r; r=a%b;
        q=(a-r)/b;
    }
    return b;
}

int main()
{
int x,y,a,b;
cout<<"请输入a和b:"<<endl;
cin>>a>>b;
cout<<"a和b的最大公约数:"<<endl;
cout<<exgcd(a,b,x,y)<<endl;
cout<<"ax+by=gcd(a,b) 的一组解是:"<<endl;
cout<<x<<" "<<y<<endl;
return 0;
}

五、例题

https://codeforces.com/contest/1152/problem/C(题解:https://blog.csdn.net/weixin_43272781/article/details/89513932

六、参考文章

https://www.cnblogs.com/haveyoueverbeen/p/4502005.html

https://www.cnblogs.com/haveyoueverbeen/p/4612753.html

https://www.cnblogs.com/haveyoueverbeen/p/4612827.html

 

全部评论

相关推荐

12-01 12:34
已编辑
广东工业大学 Java
如题,fw🐭🐭,加上准备的太晚,大三上已找不到日常实习,导致连锁反应,下学期的暑期实习找不到好的实习,导致秋招找不到中大厂,现在是中小厂Java还有考公的选择,由于有些中小厂工作强度比肩大厂,钱还少,感觉不如考公如果🐮u们是我现在这种情况,会怎么选?
负债的混子:关注你一段时间了,突然发现你头像名字都改了,想必是这段时间压力很大。关于就业还是考公的选择,就像很多牛友说的:不要美化自己没走过的路。你现在想往互联网发展,发现这条路很难走,然后想往考公发展,但是你没走过考公这条路,所以你不知道这条路的压力如何。你今年大三了,还有时间给你做选择,我希望你能够尽快的决定自己的方向,然后一条路走到黑,而不是在这里徘徊,每个人的道路是不一样的,你无法复刻别人的路,你能做的就是尽力的完善自己。 最后,我想说的是,加油,陌生人!
点赞 评论 收藏
分享
昨天 21:57
已编辑
门头沟学院 C++
点赞 评论 收藏
分享
一个菜鸡罢了:哥们,感觉你的简历还是有点问题的,我提几点建议,看看能不能提供一点帮助 1. ”新余学院“别加粗,课程不清楚是否有必要写,感觉版面不如拿来写一下做过的事情,教育经历是你的弱势就尽量少写 2. “干部及社团经历”和“自我评价”删掉 3. 论文后面的“录用”和“小修”啥的都删掉,默认全录用,问了再说,反正小修毕业前肯定能发出来 4. 工作经验和研究成果没有体现你的个人贡献,着重包装一下个人贡献
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务