[백준 문제 풀이] 1929번 소수 구하기

Junu Kim·2026년 1월 3일
post-thumbnail

[1929] 소수 구하기

난이도: ★★☆☆☆ • solved on: 2026-01-03


문제 요약

  • 문제 유형: 수학, 에라토스테네스의 체, 구현
  • 요구사항: 입력된 구간 [n, m] 안에 존재하는 모든 소수를 한 줄씩 출력해야 한다.

사용 개념

  1. 자료구조

    • boolean[] : 합성수 여부 (표시 배열)
    • StringBuilder : 출력 누적
  2. 알고리즘/기법

    • 에라토스테네스의 체 (Sieve of Eratosthenes)
    • 배수 마킹 (Marking multiples)
  3. 핵심 키워드

    • 소수 (prime number)
    • 합성수 (composite number)
    • 배수 (multiple)

풀이 아이디어

  1. 문제 분해
  • 01은 소수가 아니므로 먼저 합성수 취급(true)로 표시한다.
  • 2부터 시작해, 아직 체크되지 않은 수(소수 후보)를 만나면 그 수의 배수들을 합성수(true)로 표시한다.
  • 최종적으로 arr[i] == false인 수만 출력한다(소수만 남김).
  1. 핵심 로직 흐름

    arr[0] = arr[1] = true  // 소수 아님(합성수 취급)
    for i = 2 .. m:
        if arr[i] == true: continue
        for j = 2 while i*j <= m:
            arr[i*j] = true  // 합성수 표시
    
    for i = n .. m:
        if arr[i] == false: print i
  2. 예외 처리

    • 0, 1은 소수가 아니므로 반드시 제외한다.
    • boolean 배열의 기본값이 false이므로, “표시되면 합성수(true)” 방식으로 관리한다.

코드

import java.util.*;
import java.io.*;

class Main {
    public static boolean[] arr;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        arr = new boolean[m+1];
        StringBuilder sb = new StringBuilder();
        makeSlieve();
        
        for(int i = n; i <= m; i++){
            if(!arr[i]) sb.append(i).append("\n");
        }
        System.out.println(sb);
    }
    public static void makeSlieve(){
        arr[0] = true;
        arr[1] = true;
        for(int i = 2; i < arr.length; i++){
            if(arr[i]) continue;
            for(int j = 2; i*j < arr.length; j++){
                arr[i*j] = true;
            }
        }
    }
}

시간·공간 복잡도

  • 시간 복잡도: 대략 O(M log log M) 수준 (에라토스테네스의 체)

    • 구현상 i*j 형태로 마킹하므로 상수는 커질 수 있으나, 기본 아이디어는 체 방식이다.
  • 공간 복잡도: O(M) (boolean[m+1])


어려웠던 점

  • boolean 배열의 기본값이 무엇인지 몰라서 혼란이 있었다.
  • 처음에는 소수만 true를 기대했지만 실제로는 기본값이 전부 false라서 의도와 반대로 동작하는 문제가 생겼다.
  • 그래서 합성수만 true로 표시하고, 끝까지 false로 남은 값이 소수가 되도록 방향을 바꿔 해결했다.
  • 참고 블로그를 통해 boolean 기본값이 false임을 확인했다.

배운 점 및 팁

  • Java에서 boolean[]의 기본값은 false라서, 보통은 합성수만 true로 마킹하는 형태가 구현이 편하다.
  • 배수 마킹은 j = i*i부터 시작하거나 i<=mi <= \sqrt{m}까지만 돌리면 더 빠르게 만들 수 있다.

참고 및 링크


추가 연습 문제

profile
생각이 현실이 될 수 있도록 노력하는 중입니다.

0개의 댓글