728x90
728x90

최대 공약수(GCD)와 최소 공배수(LCM) ; 유클리드 호제법(Euclidean Algorithm)

최대 공약수(GCD; Greatest Common Divisor(Factor))

  • 두 개 이상의 자연수들의 공통인 약수들의 모임공약수(Common Divisor)라고 하고, 공약수 중에서 가장 큰 수최대 공약수(Greatest Common Divisor)라고 한다.
  • 예) 12의 약수는 {1,2,3,4,6,12} 이고 18의 약수는 {1,2,3,6,9,18}일 때, 두 수 1218공약수{1,2,3,6}이고 최대 공약수6이 된다.

 

코드

int gcd(int x, int y) {
for (int i = (x > y ? y : x); i >= 1; i--) { // 두 수의 최댓값부터 시작해서 1까지
if (x % i == 0 && y % i == 0) { // 두 수로 나누어 떨어질 경우
return i;
}
}
}
  • 두 개의 정수 x와 y의 최대 공약수는 x와 y의 최솟값보다 클 수가 없기 때문에 for 문의 초기부 i는 두 개의 정수 x와 y 중에서 최솟값으로 초기화하고 초깃값부터 1까지 회전한다.
  • 두 개의 정수 x와 y를 동시에 나눌 수 있는 첫 번째 정수가 두 수 x와 y의 가장 큰 공약수이므로, 첫 번째로 조건문을 만족하는 정수 i는 최대 공약수가 된다.

 

유클리드 알고리즘(Euclidean Algorithm) ; 유클리드 호제법

유클리드 (BC330? - BC275?)

  • 유클리드 알고리즘(Euclidean Algorithm) 또는 유클리드 호제법은 2개의 자연수의 최대 공약수(GCD)를 구하는 알고리즘이다.
  • 유클리드(Euclid, BC330? ~ BC275?)가 기원전 300년 경에 쓴 『원론』 제 7권에 나오는 가장 오래된 알고리즘이다.
    • "두 개의 자연수 A와 B에 대해서 A를 B로 나눈 나머지를 R이라고 하면(단, A ≥ B) A와 B의 최대 공약수는 B와 R의 최대 공약수와 같다."
  • 이 성질을 이용하여 B를 R로 나눈 나머지 R1을 구하고, 다시 R을 R1으로 나눈 나머지 R2를 구하고, 다시 R1을 R2로 나눈 나머지를 구하는 과정을 반복하다가 나머지가 0이 되었을 때 이 때 나누는 수 제수가 A와 B의 최대 공약수가 된다는 알고리즘이다.

 

그림으로 이해하기

  • 8개의 상자가 놓여 있는 A 그룹과 3개의 상자가 놓여있는 B 그룹이 있을 때, 두 그룹 A와 B는 모두 1개의 상자의 배수이므로 두 그룹 A와 B의 최대 공약수는 1개의 상자가 된다.

  • A와 B 그룹은 둘 다 최대 공약수가 1개의 상자이므로, 1개의 상자의 배수이다.
  • A 그룹을 B 그룹으로 나눈 나머지는 2개의 상자가 나오고, 이 2개의 상자는 A 그룹에 있었던 상자이므로 나머지로 나온 2개의 상자도 최대 공약수인 1개의 상자의 배수가 된다.
  • 다시 3개의 상자가 A 그룹이 되고, 나머지 2개의 상자가 B 그룹이 되어 같은 연산을 한다.

  • A와 B 그룹은 둘 다 최대 공약수인 1개의 상자의 배수의 배수이다.
  • A 그룹을 B 그룹으로 나눈 나머지는 1개의 상자가 나오고, 이 1개의 상자는 A 그룹에 있었던 상자이므로 나머지로 나온 1개의 상자도 최대 공약수인 1개의 상자의 배수가 된다.
  • 다시 2개의 상자가 A 그룹이 되고, 나머지 1개의 상자가 B 그룹이 되어 같은 연산을 한다.

  • A와 B 그룹은 둘 다 최대 공약수인 1개의 상자의 배수의 배수이다.
  • A 그룹을 B 그룹으로 나누면 나머지는 0개의 상자가 나오고, B 그룹에 있던 1개의 상자가 지금까지 나누었던 모든 상자 그룹들을 나눌 수 있는 최대 상자이므로 마지막으로 남은 이 1개의 상자가 최대 공약수가 되는 것이다.
  • 이것을 수학적으로 증명하면 다음과 같다.

 

수학적으로 증명하기

  • 두 수 AB가 주어졌을 때 (단, AB), 두 수 A와 B의 최대 공약수G라고 하면 다음과 같이 나타낼 수 있다.
A=Ga,B=Gb(a와 b는 서로소)
  • AB로 나눈 Q라고 하고 나머지R이라고 한다면 다음과 같이 나타낼 수 있다.
A=BQ+R
  • 여기서 BR최대 공약수G임을 증명하면 된다.
  • B=Gb 이고, R=A-BQ=Ga-GbQ=G(a-bQ) 가 된다.
B=Gb,R=G(abQ)
  • 따라서 BR공약수G가 되는데, ba-bQ서로소임을 증명하면 공약수 G 최대 공약수가 된다.
  • ba-bQ 가 서로소임은 귀류법을 써서 증명할 수 있다.
  • 만약 ba-bQ 가 서로소가 아니라고 가정한다면, ba-bQ 는 공통된 약수를 가지고 있을 것이고, 공통된 약수를 p 라고 한다면 b=np,abQ=mp 라 놓을 수 있다.
  • a=mp+bQ 가 되고 b=np 이므로 a=mp+bQ=mp+npQ=p(m+nQ) 가 된다.
  • a=p(m+nQ) 이고 b=np 가 되기 때문에 ab 는 공약수 p 를 가진다.
  • 이것은 ab 가 서로소라는 가정에 모순이 되므로 ba-bQ 서로소이다.
  • ba-bQ서로소이기 때문에 BR최대 공약수 GAB최대 공약수가 된다.
  • 따라서 AB 로 나눈Q 라고 하고, 나머지R 이라고 한다면 gcd(A,B)gcd(B,R) 과 같다.
int gcd(int x, int y) {
int r;
while (y) {
r = x % y; // (1), (4), (7)
x = y; // (2), (5), (8)
y = r; // (3), (6), (9)
}
return x;
}
  • 두 개의 정수1218xy 에 전달하고, xy 로 나눈 나머지를 r 이라고 할 때, xy 의 최대 공약수는 yr 의 최대 공약수와 같으므로 먼저 xy 로 나눈 나머지 r 을 구한 후, 같은 작업을 반복하기 위해서 x 의 값에 y 의 값을 대입하고 y 의 값에 r 의 값을 대입한다.
  • xy 로 나눈 나머지가 0 일 때, 제수 y 가 최대 공약수가 되지만, 한 번 더 다음 과정을 진행하면 x=y 에 의해서 x 의 값은 y 의 값이 되고, y=r 에 의해서 y 의 값은 0 이 되므로 최대 공약수인 x 의 값을 반환한다.

 

코드

#include <iostream>
using namespace std;
int gcd(int x, int y) {
int r;
while (r) {
r = x % y;
x = y;
y = r;
}
return x;
}
int main() {
int a, b;
cin >> a >> b;
cout << gcd(a, b) << '\n';
return 0;
}
12 18
6

 

최소 공배수(LCM; Least Common Multiple)

  • 두 개 이상의 자연수들의 공통인 배수들의 모임공배수(Common Multiple)라고 하고, 공배수 중에서 가장 작은 수최소 공배수(Least Common Multiple)라고 한다.
  • 예) 3 의 배수는 {3,6,9,12,} 이고 4 의 배수는 {4,8,12,16,} 일 때, 두 수 34 의 공배수는 {12,24,36,} 이고 최소 공배수는 12 가 된다.

 

  • 두 개의 자연수 AB최대 공약수G 라고 하고 최소 공배수L 이라고 하면 다음과 같은 관계식이 성립한다.
A×B=L×G
  • AB최대 공약수G 이므로 A=aG,B=bG (a,b 는 서로소)로 나타낼 수 있다.
  • 그러면 두 수의 최소 공배수(L)abG 가 된다.
  • 두 수 AB 를 곱하면 AB=aGbG 가 되고, 최대 공약수(G)최소 공배수(L)를 곱하면 LGabGG 가 된다.
  • 두 수 AB 의 곱은 최소 공배수인 L 과 최대 공약수인 G 를 곱한 값과 같기 때문에 최소 공배수는 알고리즘을 따로 작성하여 구하는 것이 아니라, 두 수 AB 를 곱한 후 최대 공약수 G 로 나누면 구할 수 있다.

 

코드

#include <iostream>
using namespace std;
int gcd(int x, int y) {
int r;
while (r) {
r = x % y;
x = y;
y = r;
}
return x;
}
int main() {
int a, b;
cin >> a >> b;
cout << a * b / gcd(a, b) << '\n';
return 0;
}
3 4
12

 

재귀 함수를 이용하여 최대 공약수/최소 공배수 구하기

  • 최대 공약수최소 공배수를 다음과 같이 재귀 함수를 이용하여 구할 수 있다.
// GCD : 최대공약수
int gcd(int x, int y) {
if (x == 0) return y;
else return gcd(y % x, x);
}
// LCM : 최소공배수
int lcm(int x, int y) {
return (x * y) / gcd(x, y);
}

 

참고 사이트

 

유클리드 호제법 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 유클리드 호제법(-互除法, Euclidean algorithm) 또는 유클리드 알고리즘은 2개의 자연수 또는 정식(整式)의 최대공약수를 구하는 알고리즘의 하나이다. 호제법이란

ko.wikipedia.org

 

최소공배수 - 나무위키

예시로 두 수 10, 12의 공배수를 찾고 싶다고 하자. 먼저 두 수의 배수를 쭉 나열한다. 10: 10, 20, 30, 40, 50, 60, 70, ... 12: 12, 24, 36, 48, 60, 72, ... 여기서 위아랫줄 동시에 나타나는 수가 바로 공배수이다.

namu.wiki

 

최대공약수 - 나무위키

예시로 두 수 12, 18의 공약수 및 최대공약수를 찾고 싶다고 하자. 간단하게, 두 수의 약수를 모두 나열한다. 12: 1, 2, 3, 4, 6, 12 18: 1, 2, 3, 6, 9, 18 여기서 위아랫줄 모두 같이 있는 숫자가 공약수가 된

namu.wiki

 

728x90
728x90

최대 공약수(GCD)와 최소 공배수(LCM) ; 유클리드 호제법(Euclidean Algorithm)최대 공약수(GCD; Greatest Common Divisor(Factor))코드유클리드 알고리즘(Euclidean Algorithm) ; 유클리드 호제법그림으로 이해하기수학적으로 증명하기코드최소 공배수(LCM; Least Common Multiple)코드재귀 함수를 이용하여 최대 공약수/최소 공배수 구하기참고 사이트