学习笔记 - 数论/数学 - 花式求最大公因数
一组整数的最大公约数,是指所有公约数里面最大的一个,记为
两个数的最大公约数
欧几里得算法
指路
,复杂度
欧几里得优化 -> Stein算法
已知
先把
类似欧几里得算法进行辗转相减/相除,此过程中得到的
代码实现
- 欧几里得 - 最朴素的递归
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
-
欧几里得 - 不用递归
int gcd(int a,int b){ if(b) while((a%=b)&&(b%=a)); return a+b; } -
Stein算法 - 非位运算版
int gcd(int a,int b){ int c=0; if(a==0||b==0) return a+b; while(a%2==0&&b%2==0){a/=2;b/=2;c++;} while(a%2==0)a/=2; while(b%2==0)b/=2; if(a<b) swap(a,b); while(a%=b){while(a%2==0)a/=2;if(a<b)swap(a,b);} //此处括号中a%=b 可以换为 a=(a-b)/2,但亲测int下换了会变慢一点点 return b<<c; } -
Stein算法 - 位运算版
int 下,改成位运算并不能使代码变快,反而使代码更长,可读性更差,不建议使用。
但倘若想求高精
int gcd(int a,int b){int c=0;
if(a==0)return b;if(b==0)return a;
while((!(a&1))&&(!(b&1))){a>>=1;b>>=1;c++;}
while((!(a&1)))a>>=1; while((!(b&1)))b>>=1;
if(a<b) swap(a,b);
while(a=((a-b)>>1)){while((!(a&1)))a>>=1;if(a<b)swap(a,b);}//用高精的话换了快
return b<<c;
}