算法学习 之 欧几里得算法和扩展欧几里得算法(二)

关于扩展欧几里得算法(Extended Euclidean Algorithm),我是在做青蛙的约会这一经典题目才接触到这个算法的。后面也有关于这一题的AC代码和解题思路。

内容:已知a, b,求解一组x,y,使它们满足贝祖等式: ax+by =gcd(a, b)

扩展欧几里得算法,就和它的名字一样是对欧几里得算法的扩展。何为扩展?一是,该算法保留了欧几里得算法的本质,可以求a与b的最大公约数。二是,已知a, b求解二元一次方程ax+by =gcd(a, b)的一组解(x,y)。

证明:

假设 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)

在根据多项式恒等定理(把a,b看成变量),x1=y2; y1=x2-a/b*y2;

(表面上看,就是已知方程一的一组解,可以得到方程二的一组解,已知方程二的一组解,就可以得到方程一的一组解,但是实际情况是,不可能先知道方程一的解(x1,y1)。)上述思想是递归定义的,不断地利用gcd(a,b) =gcd(b,a%b),到b=0(y的系数为0)时,由(1)的解,根据解之间的关系,最终可以得到方程ax+by =gcd(a, b)的解。

递归形式代码:

 1 #include<iostream>
 2 using namespace std;
 3
 4 int exgcd(int a,int b,int &x,int &y)
 5 {
 6      if(b==0)
 7     {
 8         x=1;
 9         y=0;
10         return a;
11     }
12     int gcd=exgcd(b,a%b,x,y);
13     int x2=x,y2=y;
14     x=y2;
15     y=x2-(a/b)*y2;
16     return gcd;
17 }
18
19 int main()
20 {
21 int x,y,a,b;
22 cout<<"请输入a和b:"<<endl;
23 cin>>a>>b;
24 cout<<"a和b的最大公约数:"<<endl;
25 cout<<exgcd(a,b,x,y)<<endl;
26 cout<<"ax+by=gcd(a,b) 的一组解是:"<<endl;
27 cout<<x<<" "<<y<<endl;
28 return 0;
29 }

  

非递归形式代码:

 1 #include<iostream>
 2 using namespace std;
 3
 4 int exgcd(int a,int b,int &x,int &y)
 5 {
 6     int x1,y1,x0,y0;
 7     x0=1; y0=0;
 8     x1=0; y1=1;
 9     x=0; y=1;
10     int r=a%b;
11     int q=(a-r)/b;
12     while(r)
13     {
14         x=x0-q*x1; y=y0-q*y1;
15         x0=x1; y0=y1;
16         x1=x; y1=y;
17         a=b; b=r; r=a%b;
18         q=(a-r)/b;
19     }
20     return b;
21 }
22
23 int main()
24 {
25 int x,y,a,b;
26 cout<<"请输入a和b:"<<endl;
27 cin>>a>>b;
28 cout<<"a和b的最大公约数:"<<endl;
29 cout<<exgcd(a,b,x,y)<<endl;
30 cout<<"ax+by=gcd(a,b) 的一组解是:"<<endl;
31 cout<<x<<" "<<y<<endl;
32 return 0;
33 }

  

运行截图:

同样有两点想说明:

1.扩展欧几里得算法是对欧几里得算法的扩展,可以求出gcd(a,b),好多人都没意识到这一点。

2.x,y可以用全局变量,参数传递就不用传引用了。

时间: 2024-10-13 19:14:42

算法学习 之 欧几里得算法和扩展欧几里得算法(二)的相关文章

算法学习 之 欧几里得算法和扩展欧几里得算法(三 完)

就像之前说的,接触到扩展欧几里得算法,是由于做到了这一题SWUST OJ 青蛙的约会之二(0481) http://www.cnblogs.com/haveyoueverbeen/p/4483218.html (查看题目信息可以戳上面的地址) 解题思路: 设输出结果为 s,则(m*s+x)-(n*s+y)= kl (k∈Z),即(n-m)*s + kl = x-y,设 a=n-m,b=l,c=x-y,即as +bk=c (ax+by=c),求最小正整数x,然后用扩展欧几里得算法,得到一组解x0 

算法学习 之 欧几里得算法和扩展欧几里得算法(一)

这是我算法学习标签下的第一篇随笔,首先我想声明,在看了很多博客后,我的想法就是,尽量不去盲目复制别人的东西,一个原因是盲目复制不一定能发现其文章中的错误,二是可以加深自己的理解程度,并且将博客写得通俗易懂,转载别人的东西一定要注明出处.还有我的一个习惯就是,把东西写短一点,所以有可能会将一个本来应在一篇文章的东西,写成好几节. Euclid Algorithm 又称辗转相除法,用途是求两个正整数a,b的最大公约数,gcd(a,b )表示a和b的最大公约数(gcd = greatest commo

noip知识点总结之--欧几里得算法和扩展欧几里得算法

一.欧几里得算法 名字非常高大上的不一定难,比如欧几里得算法...其实就是求两个正整数a, b的最大公约数(即gcd),亦称辗转相除法 需要先知道一个定理: gcd(a, b) = gcd(b, a mod b) (其中a mod b != 0)  或  b (其中a mod b == 0) 证明: 后半部分呢...是废话,于是只要证明前半部分即可. 不妨设g = gcd(a, b),于是有 a = g * A, b = g * B 且 (A, B) = 1 故gcd(b, a mod b) =

回档|欧几里得算法和扩展欧几里得算法

欧几里得算法:用于求两个非负整数a.b的最大公因数(用gcd(a,b)表示).这里用d表示,假设d一定存在. 证明:由题设知d|a,d|b(d|a代表d能整除a,即a mod d=0) 设a=kb+r,这里k和r都是整数.则r=a mod b.        我们可以让a=n1d,b=n2d.则r=(n1-k*n2)d        ∴d|r  ∴gcd(a,b)=gcd(b,a mod b) 扩展的欧几里得算法: 对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数

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

1 实现代码: #include <iostream> 2 using namespace std; 3 4 void exgcd(long long a, long long b, long long &d, long long &x, long long &y) { 5 if (b == 0) { 6 d = a, x = 1, y = 0; 7 } 8 else { 9 exgcd(b, a%b, d, y, x); y-=a/b*x; 10 } 11 } 12

【算法学习笔记】26.扫描维护法 解题报告 SJTU_OJ 1133 数星星

SJTU OJ 1133. 数星星 Description 主任和小伙伴晚上非常无聊,于是带着他的宠物狗出来走走.主任突然发现天空中有一条长度为N的字符串,里面的字符都是大写字母.于是主任和他的小伙伴们开始数星星(STAR). 主任和他的小伙伴还有宠物狗数星星的数法不太一样.小伙伴是一个很教条的人,他只喜欢有规则的东西.所以他每次会在字符串里面找最早的’S’,然后找’S’之后最早的’T’,然后找’T’之后最早的’A’,最后找’A’之后最早的’R’.也就是找一个位置最靠前的STAR的子序列.每次找

扩展欧几里得算法学习记

话说以前我刷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的所

扩展欧几里得算法------扩展欧几里德算法

扩展欧几里得算法及其应用 一.扩展欧几里得算法 扩展欧几里得算法:对于不完全为 0 的非负整数 a,b,若gcd(a,b)表示 a,b 的最大公约数,必然存在整数对x,y ,使得 ax+by = gcd(a,b). 算法过程: 设 a>b,当 b=0时,gcd(a,b)=a.此时满足ax+by = gcd(a,b)的一组整数解为x=1,y=0:当a*b!=0 时, 设 a*x1+b*y1=gcd(a,b):b*x2+(a mod b)*y2=gcd(b,a mod b): 根据欧几里得原理知 g

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

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