본문 바로가기

백준

백준2436 - 공약수

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

 

2436번: 공약수

첫째 줄에 두 개의 자연수가 빈칸을 사이에 두고 주어진다. 첫 번째 수는 어떤 두 개의 자연수의 최대공약수이고, 두 번째 수는 그 자연수들의 최소공배수이다. 입력되는 두 자연수는 2 이상 100,000,000 이하이다.

www.acmicpc.net

최대공약수와 최소공배수가 주어진다. 주어진 최대공약수를 가지는 수들 중에서 주어진 최소공배수를 만족하는 경우의 수들 중 합이 최소가 되는 수를 찾으면 된다. 단순히 약수를 분류하고 가장 중간에 위치한 약수를 답으로 선택하면 안된다. 왜냐하면 주어진 최소공배수에서 수를 분리하는 과정에서 서로 다른 두 개의 약수가 최대 공약수 외에 같은 약수를  포함할 수 있기 때문이다. 그렇기 때문에 약수 찾기를 하는 도중에 최대공약수를 구하는 유클리드 호제법을 이용하여 서로소가 되는 수를 찾는다. for문이 반복하면서 서로소가 되는 수들 중 합이 작은 수가 있으면 자동으로 갱신한다.

 

#include <iostream>
using namespace std;

//최대공약수 구하기, 재귀 호출 사용
int gcd(int x, int y) {
	if (y == 0) {
		return x;
	}
	else {
		return gcd(y, x % y);
	}
}

int main() {
	int a, b; //a는 최대 공약수, b는 최소 공배수
	int x; //서로소가 되어질 약수의 원소
	long long int res1 = 1, res2 = 1; //결과

	cin >> a >> b;

	b = b / a; //최대 공약수를 최소 공배수로 한 번 나누어 탐색 횟수를 줄인다.

	//약수 찾기
	for (int i = 1; i * i <= b; i++) {
		//약수를 찾고 약수와 상대 관계에 있는 약수(곱하면 b가 나오는 i, b/i)가 서로소 관계애 있는지 확인한다.
		if (b % i == 0 && gcd(i, b / i) == 1) { 
			x = i;
		}
	}
	
	//res1과 res2를 구한다.
	res1 = a * x;
	res2 = a * (b / x);

	cout << res1 << ' ' << res2;
}

'백준' 카테고리의 다른 글

백준2225 - 합분해  (0) 2019.10.31
백준13413 - 오셀로 재배치  (0) 2019.10.29
백준2168 - 타일 위의 대각선  (0) 2019.10.26
백준1461 - 도서관  (0) 2019.10.26
백준4158 - CD  (0) 2019.10.11