欧几里得算法
- 欧几里得算法用于求两个数的最大公约数,也叫辗转相除法
- 证明:若 a=k*b+r
则r=a%b 且r=a-k*b
所以若存在 g是a,b的最大公约数( g|a && g|b )
那么一定有 g|(a-k*b) 则一定 g|(a%b)
所以a和b的最大公约数就是b和a%b的最大公约数
- 终止条件:a%b为0是,返回此时的a,也就是a%b中的b
- 举个例子模拟一下:
a=20,b=15
20和15的最大公约数就是15和5的最大公约数
15和5的最大公约数就是5和0的最大公约数 即为5
int gcd(int a,int b){
if(!b) return a;
return gcd(b,a%b);
}
扩展欧几里得算法
- 欧几里得算法求的是两个数的最大公约数,扩展欧几里得算法可以求出
a*x+b*y=gcd(a,b) 的x,y 通解,即求出最大公约数的同时可以求出一组x和y,使得原式成立
先看一下写法(有“//”的代码很重要)
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1;y=0;
return a;
}
int ans=exgcd(b,a%b,x,y);
int xx=x;
x=y;
y=(xx-a/b*y);
return ans;
}
- 终止条件:这和欧几里得算法是一样的。不同的是,除了要返回gcd外,还要给x和y赋值。因为此时b为0,所以a*1+b*0==gcd,所以x=1,y=0;
- 递归过程:比欧几里得算法多出的步骤是给x,y一步步赋值,直到得到答案。
- 正确性证明:
设此时函数为ecgcd(a,b,x,y)
则下一次递归的函数为exgcd(b,a%b,x,y)
假设我们已经得到一组x和y(终止时得到),那么返回上一个函数时,x,y应该怎样变化?
将得到的x和y带入方程,有 b*x+a%b*y=gcd
又因为 a%b=a-a/b*b
所以得到 b*x+(a-a/b*b)*y=gcd
进一步化简 a*y+b*(x-a/b*y)=gcd
又因为 a*x+b*y=gcd
所以可以得到两个函数之间x,y的关系
原式得证