본문 바로가기
Algorithm/Baekjoon

백준 11653번

by minhi 2025. 1. 22.

백준 11653번을 풀어보았다.

 

첫번째 풀이는 시간초과가 발생하였다.

let N = Number(require('fs').readFileSync('/dev/stdin').toString())

let primeFactor = 2, output = ''

while (true) {
  while (N % primeFactor === 0) {
    N /= primeFactor
    output += `${primeFactor}\n`
  }

  if (N === 1) break

  let isPrimeNumber = false

  while (!isPrimeNumber) {
    primeFactor += 1
    for (let i = 2; i <= Math.sqrt(primeFactor); i++) {
      if (primeFactor % i === 0) {
        isPrimeNumber = false
        break
      }
      isPrimeNumber = true
    }
  }
}

console.log(output.trim())

 

먼저 나머지가 0이 될 때까지 N을 primeFactor로 나누고 (N에서 하나의 소인수 전부 뽑아내기)

 

이후 primeFactor가 소수가 될 때까지 1 증가 후 2부터 primeFactor의 제곱근까지로 나눠본다. (다음 소인수 찾기)

 

이렇게 그 다음 소수 primeFactor를 발견하면 다시 나머지가 0이 될 때까지 N을 primeFactor로 나눈다.

 

효율성은 고려하지 않고 머릿속에 바로 떠오른 로직을 구현한 것으로,

 

primeFactor의 소수 여부를 판단하는 while (!isPrimeNumber) {} 부분에서 상당한 비효율이 발생한다.

 

이전에 발견한 소수를 활용하지 않고 매번 새롭게 소수를 판별하기 때문인데,

 

예를 들어 primeFactor = 2이고 while (N % primeFactor === 0) {} 과정을 거쳤다면

 

짝수 인수는 더 이상 고려할 필요가 없고 그러므로 짝수 인수의 소수 여부를 판단할 필요도 없다.

 

그러나 위 코드에서는 primeFactor를 1씩 증가시키며 이런 경우에 대해서까지 중복적으로 소수 여부를 판단하고 있다.

 

아래 코드는 이러한 중복을 해결해준다.

let N = Number(require('fs').readFileSync('/dev/stdin').toString())

if (N === 1) return

let output = ''

for (let i = 2; i <= Math.sqrt(N); i++) {
  while (N % i === 0) {
    output += `${i}\n`
    N /= i
  }
}

if (N > 1) {
  output += `${N}\n`
}

console.log(output.trim())

 

while (N % i === 0) 만으로 인수 여부 확인은 물론 소수 여부 확인, 즉 while (!isPrimeNumber) {} 의 역할까지 수행할 수 있다.

 

N이 합성수일 경우 이미 앞서 소인수들에서 처리되었을 것이므로 while (N % i === 0) 이 참이 되도록 하는 i는 무조건 소인수이다.

'Algorithm > Baekjoon' 카테고리의 다른 글

백준 1157번  (0) 2025.01.23
백준 2581번  (0) 2025.01.20
백준 1978번  (0) 2025.01.17
백준 9506번  (0) 2025.01.17
백준 2501번  (0) 2025.01.16