辗转相除法求gcd
定理: g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a,b) = gcd(b,a\space mod \space b) gcd(a,b)=gcd(b,a mod b)
证明:令 c = g c d ( a , b ) c=gcd(a,b) c=gcd(a,b),不妨设 a = m c , b = n c , g c d ( m , n ) = 1 a=mc,b=nc,gcd(m,n)=1 a=mc,b=nc,gcd(m,n)=1
再设 a = k × b + r a=k\times b+r a=k×b+r
则 r = m c − k n c = ( m − k n ) × c r=mc-knc=(m-kn)\times c r=mc−knc=(m−kn)×c
所以 c c c也是 r r r的因数
所以 g c d ( b , a m o d b ) = g c d ( b , k ) = g c d ( n c , ( m − k n ) c ) = c gcd(b,a\space mod \space b)=gcd(b,k)=gcd(nc,(m-kn)c)=c gcd(b,a mod b)=gcd(b,k)=gcd(nc,(m−kn)c)=c
由于 g c d ( m , n ) = 1 gcd(m,n)=1 gcd(m,n)=1
所以 g c d ( n , m − k n ) = 1 gcd(n,m-kn)=1 gcd(n,m−kn)=1
所以 g c d ( a , b ) = g c d ( b , a m o d b ) = c gcd(a,b)=gcd(b,a\space mod \space b)=c gcd(a,b)=gcd(b,a mod b)=c
Code
void gcd(int a,int b){
return (a%b==0)?b:gcd(b,a%b);
时间复杂度
由于每次 a a a至少减少一半,所以最大时间复杂度为 O ( l o g n ) O(logn) O(logn)。
值得一提的是,对于上述函数,其运行最慢的数据为著名的 f i b o n a c c i fibonacci fibonacci数列,原因也很简单,因为每次 a m o d b a\space mod\space b a mod b都会使 a a a刚好减少一半多一点。
求lcm
由公式得 g c d ( i , j ) ∗ l c m ( i , j ) = i ∗ j gcd(i,j)*lcm(i,j)=i*j gcd(i,j)∗lcm(i,j)=i∗j
所以 l c m ( i , j ) = i ∗ j g c d ( i , j ) lcm(i,j)=\frac{i*j}{gcd(i,j)} lcm(i,j)=gcd(i,j)i∗j
公式证明也很简单,从质因子的方向可以方便证明