这一段是2018暑假写的
发现自己一学期没有写数论,啥都不会了!!!惊讶!!!!!
gcd(a,b)=gcd(a,b%a)
注意:写代码时候递归的时候一定要确保a<b,否则代码不好写,还会出现奇怪的bug,停止条件是a==0.
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int gcd(int a,int b)
{
if(a>b) swap(a,b);
if(a==0) return b;
else
{
gcd(a,b%a);
}
}
int main()
{
scanf("%d%d",&n,&m);
printf("%d",gcd(n,m));
return 0;
}
下面这一段是很久以前写的了!
首先让我们先来普及一下,关于gcd的知识,这里几个字就可以搞定,gcd(a,b)就是指a,b的最大公约数,我靠,你可能会说这个有什么用呢?
不要着急,我们马上就会进行讲解:
首先先来普及一些基本概念:
首先他们必须满足贝祖等式(好高大上的名字啊!): ax+by = gcd(a, b)。
于是由这个定理,我们成功推出了:(说实话我TM也没有听懂是怎么推的,呵呵!)
所以,我们由gcd函数的知识,可以成功的推出,如下两个递归时的方程:
ax+by=gcd(a,b);
因为a=a%b+(a/b)*b;
带入化简后:b((a/b)*x+y)+(a%b)*x=gcd(b,a%b);
下面为证明过程:
设:a>b。
推理1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
//-------------------------------------------------------------
推理2,ab!=0 时
设 ax+by=gcd(a,b);//important
bx1+(a%b)y1=gcd(b,a%b);
根据正常欧几里德原理有 gcd(a,b)=gcd(b,a%b);
则:ax+by=bx1+(a%b)y1;
因为a=a%b+(a/b)*b;代入
即:ax+by=bx1+(a-(a/b)*b)y1=ay1+bx1-(a/b)*by1=ay1+b(x1-(a/b)*y1);
由此得:x=y1 ,y=x1-(a/b)*y1;
//-------------------------------------------------------------
这样我们就得到了求解 x,y 的方法:x,y 的值基于 x1,y1.
上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。
这个推理应该非常的完美了吧!
我认为这份推理很不错的诠释了我给lry讲了半天的东西是怎么来的(因为他设了两个变量),所以讲的非常清楚,点赞!
那么相信大家gcd应该是没有什么问题了:
下面是代码实现:
#include<bits/stdc++.h>
using namespace std;
int a,b,x,y,s;
void exgcd(int a,int b ,int &x,int &y)
{
if(a==0)
{
x=0;
y=1;
}
else
{
exgcd(b%a,a,x,y);
int swap;
swap=x;
x=y-(b/a)*x;
y=swap;
}
}
int main()
{
a=12;b=30;
s=6;
exgcd(a,b,x,y);
printf("ax+by=```
");
printf("x=%d y=%d",x,y);
return 0;
}
附件(网络资料):
听说有非递归版!
http://anh.cs.luc.edu/331/notes/xgcd.pdf
http://math.cmu.edu/~bkell/21110-2010s/extended-euclidean.html
如果你还是没有看懂
下面有从《计算机程序设计艺术》转载的证明方法,仅供参考:
证明(1):
算法首次转到E2时,由上表,显然等式成立。
步骤 E2,E3 并不会改变等式的正确性。
所以只需要证明步骤 E4 不改变他们的正确性就可以了。
执行 E4 之前,
a'm + b'n = c (*)
am + bn = d (**)
成立。
a'm + b'n = c = qd + r;
a'm + b'n - q(am + bn) = r;
(a' - qa)m + (b' - qb)n = r (***)
执行 E4 之后,c←d, d←r, t←a', a'←a, a←t-qa, t←b', b'←b, b←t-qb;
所以
(**)变为 a' + b' = c
(***)变为 am + bn = d
所以步骤 E4 不改变等式的正确性,得证。
下面强势给出非递归版代码:(我也好像有点懂!)
int exgcd(int m, int n, int &x, int &y) {
if (n == 0) {
x = 1; y = 0;
return m;
}
int a, a1, b, b1, c, d, q, r, t;
a1 = b = 1;
a = b1 = 0;
c = m; d = n;
q = c/d; r = c%d;
while (r) {
c = d;
d = r;
t = a1;
a1 = a;
a = t - q * a;
t = b1;
b1 = b;
b = t - q * b;
q = c/d;
r = c%d;
}
x = a; y = b;
return d;
}
(以上代码为转载)
相关练习题
另一篇洛谷博客: