欧几里德算法又称辗转相除法,是指用于计算两个正整数a,b的最大公约数。
算法描述: g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b) = gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)
运行实例:
输入a=15,b=10
g c d ( a , b ) = g c d ( 15 , 10 ) = g c d ( 10 , 5 ) = g c d ( 5 , 0 ) \large gcd(a,b)=gcd(15,10)=gcd(10,5)=gcd(5,0) gcd(a,b)=gcd(15,10)=gcd(10,5)=gcd(5,0)
对于一个非零数和0的最大公约数一定是非零数本身。于是 g c d ( 5 , 0 ) = 5 gcd(5,0)=5 gcd(5,0)=5
根据欧几里得算法得出我们在上述过程中最大公约数没有改变,于是得出gcd(15,10) = 5
同时可以证明在4.785lgN + 1.6723步之类,之内必定会有b会成为0,而b为0恰好就是递归的结束条件。就可以在之内寻找到a和b两个数的最大公约数,所以这是一个高效的寻找最大公约数的算法。
算法证明:
先介绍一个竖线这个符号,a|b 表示a整除b。
设 z ∣ x , z ∣ y 则 z ∣ ( y − x ) a ∗ z = x b ∗ z = y ( a − b ) ∗ z = ( y − x ) 设z|x,z|y则z|(y-x)\\ a*z=x\\ b*z=y\\ (a-b)*z=(y-x) 设z∣x,z∣y则z∣(y−x)a∗z=xb∗z=y(a−b)∗z=(y−x)
所以如果z如果是x,y的因子,则z一定是y-x的公因子,所以可以发现换成数学表述形式就是
g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b) = gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)
代码实现:
int gcd(int a,int b){
if(b == 0) return a;
else return gcd(b,a%b);
}
拓展欧几里得算法是用来在已知(a,b)时,求解一组(p,q),使得 a ∗ x + b ∗ y = c a*x+b*y=c a∗x+b∗y=c
首先根据裴蜀定理可以证明解一定存在,这不是本文的重点,于是有兴趣的可以自行查阅资料。
定理1: 对于方程 a ∗ x + b ∗ y = c 该 方 程 等 价 于 a ∗ x ≡ c ( m o d b ) a*x+b*y=c该方程等价于a*x\equiv c(mod\ b) a∗x+b∗y=c该方程等价于a∗x≡c(mod b),该方程有整数解的充要条件是gcd(a,b)|c
我们再回顾上面欧几里得算法的实现过程
\begin{align}
\because gcd(a,b)=gcd(b,a%b)\
\therefore pa+qb & = gcd(a,b)\
& = gcd(b,a%b) \
& = pb+q(a%b) \
& = pb+(b-a/bq)*b \
\end{align}