https://www.acmicpc.net/problem/1934
문제
두 자연수 A와 B에 대해서, A의 배수이면서 B의 배수인 자연수를 A와 B의 공배수라고 한다. 이런 공배수 중에서 가장 작은 수를 최소공배수라고 한다. 예를 들어, 6과 15의 공배수는 30, 60, 90등이 있으며, 최소 공배수는 30이다.
두 자연수 A와 B가 주어졌을 때, A와 B의 최소공배수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 둘째 줄부터 T개의 줄에 걸쳐서 A와 B가 주어진다. (1 ≤ A, B ≤ 45,000)
출력
첫째 줄부터 T개의 줄에 A와 B의 최소공배수를 입력받은 순서대로 한 줄에 하나씩 출력한다.
코드1
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
vector<int> vec;
int main(void) {
int a, b;
int ans1=1;
int T;
int num;
cin >> T;
for(int i=0; i<T; ++i){
ans1 = 1;
num = 2;
cin >> a >> b;
while(num <= min(a,b)){
if(a%num == 0 && b%num==0){
a/=num;
b/=num;
ans1*=num;
num=2;
}
else{
num++;
}
}
cout <<ans1*a*b<<'\n';
}
return 0;
}
처음으로 작성한 코드이다. 단순히 2부터 시작해서 a와 b중 작은 수까지 두수를 나눠 최대공약수와 최소공약수를 구하는 코드이다.
물론 이렇게 무식하게 풀어도 정답을 얻을 수 있다. 하지만 더 간편하고 좋은 알고리즘이 있어 알아보려 한다.
코드2
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
vector<int> vec;
int main(void) {
int a, b;
int ans;
int T;
int num;
cin >> T;
for(int i=0; i<T; ++i){
num = 2;
cin >> a >> b;
int temp1 = a;
int temp2 = b;
a = max(a,b);
b = min(temp1,b);
while(1){
int k = a % b;
if(k == 0){
ans = b;
break;
}
else{
a = b;
b = k;
}
}
cout << temp1*temp2 /ans<<'\n';
}
return 0;
}
유클리드 알고리즘을 이용한 풀이이다.
유클리드 호제법 : 2개의 자연수(또는 정식) a, b에 대해서 a를 b로 나눈 나머지를 r이라 하면(단, a>b), a와 b의 최대공약수는 b와 r의 최대공약수와 같다. 이 성질에 따라, b를 r로 나눈 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다.
예를 들어, 1071과 1029의 최대공약수를 구하면
1. 1071 % 1029 = 42
2. 1029 % 42 = 21
3. 42 % 21 = 0
21로 나누었을때 최종적으로 나머지가 0이 나왔으므로 21이 최대공약수이다.
이때, 최소공배수를 구하려면 원래 a, b의 값을 최대공약수로 나눈 값에 최대공약수를 곱해주면 된다.
'PS > 기타 알고리즘' 카테고리의 다른 글
[24313] (C++) 알고리즘 수업 - 점근적 표기 1 (0) | 2023.03.19 |
---|---|
[2981] (C++) 검문 (0) | 2023.02.06 |
[1004] 어린 왕자 (0) | 2023.02.05 |
[3053] 택시 기하학 (0) | 2023.02.05 |
[2477] 참외밭 (0) | 2023.02.05 |