수학, 211011
문제
두 개의 자연수를 입력받아 최대 공약수와 최소 공배수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에는 두 개의 자연수가 주어진다. 이 둘은 10,000이하의 자연수이며 사이에 한 칸의 공백이 주어진다.
출력
첫째 줄에는 입력으로 주어진 두 수의 최대공약수를, 둘째 줄에는 입력으로 주어진 두 수의 최소 공배수를 출력한다.
예제 입력 1
24 18
예제 출력 1
6
72
My solution
두 자연수 A, B(A ≥ B)에 대하여 A ÷ B=q ····· r (q ≠0)에서 A=Bq+r (0≤ r 〈 B)이다.(나눗셈의 정리) A와 B의 최대공약수는 Bq+r과 B의 최대공약수와 같다. [출처] [최대공약수 쉽게 구하는 법]-유클리드 호제법|작성자 eandimath
A와 B의 최대공약수를 구하려고 하면 나눗셈 정리로 B를 이용해 A를 만들어주는 Bq+r을 먼저 수행했을 때 Bq+r과 B의 최대공약수를 구하는 것과 다름없다.
그렇다면 Bq+r과 B의 관계에서 Bq와 B만 비교했을 때는 어차피 B가 최대공약수가 된다. 그렇다면 B와 r사이의 최대 공약수를 구하는 것이 문제가 된다. 이걸 바로 구하지 말고 여기서 B를 다시 나눗셈 정리로 변경해서 최종적으로 r이 0이 될 때까지 반복한다. 이렇게 되면 마지막에 남은 B가 구하려고 하는 최대공약수가 된다.
예시) gcd(120,54)
120=54×2+12 이므로 gcd(120,54)=gcd(54,12)
54=12×4+6 이므로 gcd(54,12)=gcd(12,6)
12=6×2+0 이므로 gcd(12,6)=gcd(6,0)
따라서 gcd(120,54)=gcd(6,0)=6
예시를 보면 함수를 재귀적으로 호출하는 것이 좋아보인다. 나머지가 0이 됐을 때 재귀를 탈출하면 된다.
최소공배수는 a * b 를 a와 b의 최대공약수로 나누면 쉽게 구할 수 있다. 최대공약수를 찾기위해 유클리드 호제법을 이용하면 쉽다. 유클리드 호제법이란, a 와 b의 최대공약수를 구하기위해 a%b=c를 사용한다.
소스코드
function solution(i) {
const input = i
.toString()
.trim()
.split(" ")
.map((v) => parseInt(v));
// 최대 공약수
function gcd(a, b) {
return b == 0 ? a : gcd(b, a % b);
}
let div = gcd(input[0], input[1]);
// 최소 공배수
function lcm(a, b, div) {
return (a * b) / div;
}
let l = lcm(input[0], input[1], div);
let answer = div + "\n" + l;
console.log(answer);
// return answer;
}
test("solution", () => {
expect(solution("24 18")).toStrictEqual("6\n72\n");
expect(solution("120 54")).toStrictEqual("6\n1080");
});