C언어/BAEKJOON

[백준] 2609. 최대공약수와 최소공배수

너굴맨이해치움 2022. 5. 28. 08:45

: solved.ac class 2 - silver 5

 

https://www.acmicpc.net/problem/2609

 

2609번: 최대공약수와 최소공배수

첫째 줄에는 입력으로 주어진 두 수의 최대공약수를, 둘째 줄에는 입력으로 주어진 두 수의 최소 공배수를 출력한다.

www.acmicpc.net

 

 

예제 입력

24 18

예제 출력

6
72

 

정답

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int eu_al(int a, int b)
{
	if (b == 0)
		return a;
	else
		return eu_al(b, a % b);
}

int main()
{
	int a, b, tmp, mul, div;

	scanf("%d %d", &a, &b);

	if (a < b) {
		tmp = b;
		b = a;
		a = tmp;
	}

    div = eu_al(a, b);
	mul = (a * b) / eu_al(a, b);

	printf("%d\n%d\n", div, mul);

	return 0;
}


해설

 

: 유클리드 호제법(Euclidean algorithm)을 이용한다.

 

보통 최대공약수와 최소공배수 문제는 for문 등으로 계속해서 나눠가는 방식을 택하는데, 구글링해 보니 최소공약수를 구하는 신기한 방식이 있어서 풀이에 한번 채택해 보았다.

골자는 이러하다. '최대공약수는 두 수를 공통되게 나눌 수 있는 가장 큰 수이다 -> 그러면 두 수 중 큰 수를 작은 수로 나누어서, 나머지가 생긴다면 그 나머지로 두 수를 나눌 수 있는지 확인해보면 어떨까?'

 

예시를 보면 어느 정도 감이 올 것이다. 큰 수는 작은 수들의 곱과 합으로 쪼갤 수 있다는 발상에서 착안한 방법인데,

큰 수를 작은 수의 곱과 나머지로 나타내고 -> 작은 수를 나머지의 곱과 또 그 나머지로 나타내고 -> ... 의 반복이다.

같은 과정을 대상만 바꾸어 계속 반복한다. 즉, 재귀로 쉽게 구현할 수 있다.

 

 

 

과정을 보자면 이러하다. 먼저 최대공약수/최소공배수를 구할 두 수를 입력받은 뒤,

크기를 비교하여 a에는 큰 수가, b에는 작은 수가 오도록 한다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a, b, tmp, mul, div;

	scanf("%d %d", &a, &b);

	if (a < b) {
		tmp = b;
		b = a;
		a = tmp;
	}
	//a가 b보다 작을 경우 swap해서
	//a에는 큰 수, b에는 작은 수가 오도록 하기

 

최대공약수를 구하는 것은 eu_al이라는 재귀함수로 나타냈다.

최소공배수는 두 수의 곱을 최대공약수로 나눈 값이므로, 이에 맞게 구현해주면 된다.

	div = eu_al(a, b);
	//최대공약수
	mul = (a * b) / eu_al(a, b);
	//최소공배수
	//(최소공배수는 두 수의 곱을 최대공약수로 나눈 값)

	printf("%d\n%d\n", div, mul);

	return 0;
}

 

eu_al 함수의 내용은 이러하다. 이해만 하면 구현은 정말 간단하다.

큰 수를 작은 수의 곱과 나머지로 나타내고 -> 작은 수를 나머지의 곱과 또 그 나머지로 나타내고 -> ... 의 과정을 반복하고

나머지가 0이 되는 시점이 오면 그 시점의 피젯수가 바로 최대공약수이다.

//유클리드 호제법으로 최대공약수를 구하는 함수 (재귀함수화)
int eu_al(int a, int b)
{
	if (b == 0)
		return a;
	else
		return eu_al(b, a % b);
}