문제
프로그래머스 1단계 두 문제 중에 첫번째 문제가 이 문제와 유사한 문제였다.
왠걸.... 알고리즘이 생각이 안나... 분명 이 문제를 풀고 심지어 발표도 했었는데 이게 기억이 안나다니
진짜 심각성을 느끼고 기초부터 다시 잡기 위해 10달전 문제를 리뷰해보려고 한다^^
🔎 해결 방법
이 문제의 알고리즘이 기억나지 않았던 이유는 단순하다. 그 당시에 내것으로 만들지 않았기 때문...
최대공약수를 구하기 위해서는 유클리드 호제법이라는 알고리즘을 사용하면 되고
최소공배수를 구하기 위해서는 미리 구해두었던 최대공약수를 활용해서 구할 수 있다.
이것을 외우기만 하고 제대로 이해하지 못했기 때문에 생각이 나지 않았던 것 같다.
◆ 최대공약수 구하는 방법
먼저 유클리드 호제법에 대해 알아보자
❓ 유클리드 호제법이란?
2개의 자연수 또는 정식의 최대공약수를 구하는 알고리즘의 하나로,
호제법(互 서로 호, 除 덜 제)이란 말은 두 수가 서로 상대방 수를 나누어서 결국 원하는 수를 얻는 알고리즘을 말한다.
2개의 자연수(또는 정식) a, b에 대해서 a를 b로 나눈 나머지를 r이라 하면(단, a > b), a와 b의 최대공약수는 b와 r의 최대공약수와 같다.
이 성질에 따라, b를 r로 나눈 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다.
📖 유클리드 호제법 증명
a, b를 다음과 같이 정의하고 (a >= b / 알파, 베타는 서로소)
a, b 사이에 다음과 같은 관계가 있다고 하면
r은 다음과 같이 정의할 수 있다.
a, b를 각각 제일 위에서 정의했던대로 대치하고 이를 변형하면 아래와 같다.
이제 식이 다음과 같이 정리가 됐다.
위에서 알파, 베타가 서로소라고 가정했으므로 a, b의 최대공약수는 G이다.
b, r의 최대공약수 역시 G임을 보이기 위해서는 베타와 (알파 - 베타*q)가 서로소임을 보이면 된다.
이것의 증명은 귀류법(결론을 부정함으로써 가정이 명제가 참임을 보이는 방법)을 사용하면된다.
이 방법은 구글링을 통해 찾아보도록 하자^^
결국 유클리드 호제법을 사용하여 나머지가 0이 될 때까지 함수를 재귀적으로 호출하면 끝!
◆ 최소공배수 구하는 방법
최소공배수는 두 수를 곱한 것을 최대공약수로 나누면 바로 구할 수 있다.
그 이유를 예시와 함께 설명해보겠다
우리가 흔히 최소공배수를 구할 때는 아래와 같은 방법을 사용한다.
여기서 파란색 숫자들만 곱하면 최소공배수가 되는데
이것은 즉,
이와 같이 변형할 수 있고 간소화 하면
이렇게 된다! 결국 두 수를 곱한 것을 최대공약수로 나누면 되는 것이다.
💡 내 코드(C)
/*최대공약수와 최소공배수*/
/*최소공배수 * 최대공약수 = a * b*/
#include <stdio.h>
int gcd(int a, int b) //최대공약수
{
return (a % b)!=0 ? gcd(b, a%b) : b; // 유클리드 호제법
}
int lcm(int a, int b) // 최소공배수
{
return a * b / gcd(a, b);
}
int main(void)
{
int a, b;
scanf("%d %d", &a, &b);
if (a > b) {
printf("%d", gcd(a, b));
printf("\n");
printf("%d", lcm(a, b));
}
else {
printf("%d", gcd(a, b));
printf("\n");
printf("%d", lcm(b, a));
}
}
'Baekjoon > 수학' 카테고리의 다른 글
[1475] 방 번호 (0) | 2020.02.09 |
---|---|
[1085] 직사각형에서 탈출 (0) | 2020.02.08 |
[2839] 설탕 배달 (0) | 2020.02.08 |
[1110] 더하기 사이클 (0) | 2019.09.15 |
[2775] 부녀회장이 될테야 (0) | 2019.05.11 |