数论初步——gcd(最大公约数)与lcm(最小公倍数)

辗转相除法求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)

证明:令 c = g c d ( 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 = k × b + r a=k\times b+r

r = m c k n c = ( m k n ) × c r=mc-knc=(m-kn)\times c

所以 c c 也是 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

由于 g c d ( m , n ) = 1 gcd(m,n)=1

所以 g c d ( n , m k n ) = 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

Code

void gcd(int a,int b){
    return (a%b==0)?b:gcd(b,a%b);

时间复杂度

由于每次 a a 至少减少一半,所以最大时间复杂度为 O ( l o g n ) O(logn)

值得一提的是,对于上述函数,其运行最慢的数据为著名的 f i b o n a c c i fibonacci 数列,原因也很简单,因为每次 a   m o d   b a\space mod\space b 都会使 a a 刚好减少一半多一点。

求lcm

由公式得 g c d ( i , j ) l c m ( 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)}

公式证明也很简单,从质因子的方向可以方便证明

发布了45 篇原创文章 · 获赞 18 · 访问量 4759

猜你喜欢

转载自blog.csdn.net/wljoi/article/details/101227686