【学习笔记】求最大公约数算法及扩展欧几里得算法介绍
求最大公约数算法介绍
1.更相减损术
算法原理:欲求\(a\)和\(b\)的最大公约数,设\(gcd(a,b)\)为\(m\),故\(a\)是\(m\)的倍数,\(b\)是\(m\)的倍数,则\(a-b\)自然也是\(m\)的倍数,故有$$gcd(a,b)=gcd(b,a-b)(假定a>b)$$
当\(b\)变为0,则\(a\)便是我们所需求解的最大公约数。
代码如下:
ll minus_gcd(ll x,ll y){
while(x!=y){
if(x<y) swap(x,y);
x-=y;
}
return x;
}
时间复杂度分析:避免了效率较低的取模运算,但算法不稳定,最坏时间复杂度为\(O(max(a,b))\)。举例:\(a\)为10000,\(b\)为1,则需迭代9999次。
注:最好不要递归写,更相减损术的递归次数可能很大,导致爆栈
2.辗转相除法
算法原理:总体思路与更相减损术类似,但使用取模避免了多次相减。
代码如下:
ll mod_gcd(ll x,ll y){
return y==0?x:mod_gcd(y,x%y);
}
时间复杂度分析:总体上时间复杂度为\(O(log(max(a,b)))\),但因取模效率较低,在实际数据中有所波动,对于大数据尤其是高精度较不方便。
3.更相减损术与位运算结合
算法原理:欲求\(gcd(a,b)\),可分情况讨论:
1.若\(a\)与\(b\)均是偶数,则$$gcd(a,b)=2*gcd(a/2,b/2)=gcd(a>>1,b>>1)<<1$$
2.若\(a\)是奇数,\(b\)是偶数,则$$gcd(a,b)=gcd(a,b>>1)$$
3.若\(a\)是偶数,\(b\)是奇数,则与2类似。
4.若\(a\)与\(b\)均是奇数,则$$gcd(a,b)=gcd(b,a-b)(假定a>b)$$\(a-b\)必定是偶数,可使用移位运算。
递归结束条件:\(b=0\)。
代码如下:
ll bit_gcd(ll x,ll y){
if(y==x) {
return x;
}
if(x<y) swap(x,y);
if(!x&1&&!y&&1) return bit_gcd(x>>1,y>>1)<<1;
else if(x&1&&!y&1) return bit_gcd(x,y>>1);
else if(!x&1&&y&1) return bit_gcd(x>>1,y);
else return bit_gcd(y,x-y);
}
时间复杂度分析:总体时间复杂度为\(O(log(max(a,b)))\),比较优秀。
扩展欧几里得定理介绍
问题引入:给定整数a、b、c,求一组整数解x、y使\(ax+by=c\)成立
引理:若上述方程有解,则\(gcd(a,b)|c\)成立。
证明:使上述方程两边同除以\(gcd(a,b)\),左侧仍为整数,故右侧也应为整数,故\(gcd(a,b)|c\)。
所以问题转化为\(ax'+by'=gcd(a,b)\),设\(x\)与\(y\)为原方程的解,则有$$x=x'(c/gcd(a,b)),y=y'(c/gcd(a,b))$$
故最后求得x'与y'之后应及时求出x与y。
由辗转相除法知,
在计算机中,\(a\;mod\;b=a-b*(a/b)\),因此上式也可以转化为
因此,有下列等式关系:\(x'=y''、y'=x''-(a/b)*y''\)
采用递归,当b=0时回溯,逐层求出x与y的值,最后得到最初的\(x'\)与\(y'\),并进一步得到\(x\)与\(y\)。
代码如下:
inline void ex_gcd(ll a,ll b,ll x,ll y){
if(b==0) {
x=1;y=0;
return;
}
ex_gcd(b,a%b,x,y);
ll tmp=x;
x=y;y=tmp-a/b*y;
}
注:上面的代码仅是得到了\(x'\)与\(y'\)。