最大公约数与最小公倍数
若自然数d同时是自然数a和b的约数,这称d是a和b的公约数。在所有a和b的公约数中最大的一个称为a和b的最大公约数,记为gcd(a,b)。
若自然数m同时是自然数a和b的倍数,这称m是a和b的公倍数。在所有a和b的公倍数中最小的一个称为a和b的最小公倍数,记为lcm(a,b)。
对于任意a,b属于自然数,gcd(a,b)*lcm(a,b)=a*b
证明:
设d=gcd( a , b ),a0 = a / d,b0=b/d,gcd(a0,b0)=1,lcm(a0,b0)=a0*b0.
lcm( a , b )=lcm( a0 * d, b0 * d )=lcm(a0,b0)*d=a0*b0*d=a*b/d
因此lcm(a,b)*gcd(a,b)=a*b;
最大公约数
1).九章算术·更相减损术
对于任意a,b属于自然数,a>=b,有gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)
对于任意a,b属于自然数,有gcd(2a,2b)=2gcd(a,b)
证明:
后者显然成立。
设d是a,b的任意公约数,因为 d | a , d | b ,所以 d | (a-b)(a>=b)。
因此d也是b,a-b的公约数。反之则成立。故a,b的公约数集合与b,a-b的公约数
集合相同。对于a,a-b同理,最大公约数也相等。
欧几里得算法
对于任意a,b属于自然数,b不等于0,gcd(a,b)=gcd(b,a mod b).
证明:
若a<b,那么 a mod b = a,那么gcd(b,a mod b)=gcd(b,a)=gcd(a,b)
若a大于等于b,设 a = q * b + r (0 <= r <= b),推出 r = a mod b。
再设 d是a,b的公约数,因此可以推出 d | q * b 。
那么可以由 d | a, d | q * b,推出 d | ( a - d * q ),
那么 d | r => d | (a mod b)。
因此gcd(a,b)=gcd(b,a%a);
代码如下:
int gcd(int a,int b){
return b==0 ? a : gcd( b % a);
}
欧几里得算法求最大公约数的时间复杂度为O(log( a + b))。欧几里得算法是最常用的求最大公约数的方法。但是在高精度运算当中,高精度除法(取模)不容易实现,所以我们应当考虑用更相减损法来代替欧几里得算法。
扩展欧几里得算法
对于任意的整数a和b来说,都存在 a * x + b * y = gcd ( a , b )有解。
如何求解?
ax + by = gcd ( a , b ) = gcd( b , a % b )
b * x1 + ( a % b ) * y1 = gcd ( b , a % b )
a * x + b * y = b * x1 + ( a % b ) * y1
a * x + b * y = b * x1 + (a - [ a / b ] * b) * y1
a * x + b * y = a * y1 + b * x1 -[ a / b ] * b * y1;
由上可知: x = y1 , y = x1 - [ a / b ]*y1.
那么我们可以用递归求解 a * x + b * y = gcd ( a , b )的解,负载度为lg n。
代码如下:
void extend_gcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return;
}
extend_gcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-(a/b)*y;
}
参考:李煜东《算法竞赛进阶指南》
道阻且长
自己选的路 跪着也要走完