[백준] 4134 - JAVA

Sunwu Park·2024년 1월 25일
0

Algorithm

목록 보기
7/12

문제
정수 n(0 ≤ n ≤ 4*109)가 주어졌을 때, n보다 크거나 같은 소수 중 가장 작은 소수 찾는 프로그램을 작성하시오.

입력
첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다.

출력
각각의 테스트 케이스에 대해서 n보다 크거나 같은 소수 중 가장 작은 소수를 한 줄에 하나씩 출력한다.

예제 입력 1

3
6
20
100

예제 출력 1

7
23
101

느낀점
초반에는 그저 에라토스테네스의 체를 이용해서 풀면된다고 생각하여 쉬운문제인줄 알았으나 생각보다 따져야할 것이 많았다. 또한 에라토스테네스의 체를 어떻게 코드로 짜는지 까먹어서 좀 슬펐다.

[출처: https://velog.io/@thsdnjst/Java-%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98-%EC%B2%B4]

/*
소수 정리에 따르면
1. N이 충분히 큰 수라면 N 근처에 존재하는 소수들 사이의 평균 간격은 대략적으로 lnN이다
2. 어떤 큰 수 N에 가까운 정수 하나를 무작위로 고를때, 그 정수가 소수일 확률은 1/lnN에 근사
3. 소수의 분포는 더 큰 수로 갈수록 적어진다
*/

// "n이 소수인지 판별하려는 수 일때, n의 양의 제곱근 보다 작은 소수로 나누어 떨어지지 않으면 n은 소수이다."
// 따라서, 4*10^9 이상의 수에 대해 소수임을 판별하려면 sqrt(4*10^9) = 63,245 보다 작은 소수들로 나누자.
// 소수 정리에 따라 4*10^9 근처의 소수의 간격은 ln(4*10^9)이므로
// 즉 4*10^9이 소수가 아니라 해도 4*10^9 + ln(4*10^9) 이내에는 소수가 존재한다.
// 넉넉잡아 63,300 크기의 배열을 선언하자.
// static final int ARR_SIZE = 63300;
// static int[] primeNum = new int[ARR_SIZE];

위의 블로그에서 설명한것 처럼 먼저 가장 큰 소수를 미리 지정해놓고 소수와 비소수를 적어놓고 푸니 훨씬 더 빨리 풀린것 같다. 너무 정리를 잘해주셨다. 그저 실버를 다신 무시하지 않을 것이다.

코드

package baekjoon.algorithm.Problems.P4134;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {

        final int ARR_SIZE = 63300;
        int[] primeNum = new int[ARR_SIZE];

        int T;
        long n;
        boolean isPrime = false;

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        for (int i = 0; i < ARR_SIZE; i++) {
            primeNum[i] = 1;
        }
        // 소수 배열 구하기 - 에라스토테네스의 체
        // 1이면 소수이고, 0이면 소수가 아니다.
        primeNum[0] = 0;
        primeNum[1] = 0;

        for (int i = 2; i < ARR_SIZE; i++) {
            for (int j = 2; i * j < ARR_SIZE; j++) {
                primeNum[i * j] = 0;
            }
        }

        // 입력 받은 수 n에 대하여 n보다 크거나 같은 소수 중 가장 작은 소수를 구해보자.
        T = Integer.parseInt(br.readLine());

        for (int t = 0; t < T; t++) {
            n = Long.parseLong(br.readLine());
            if (n <= 1) {
                System.out.println(2);
            } else {
                for (long i = n;; i++) {
                    int m = (int) Math.sqrt(i);
                    isPrime = true;
                    for (int j = 1; j <= m; j++) {
                        if (primeNum[j] == 1) {
                            if (i % j == 0) {
                                isPrime = false;
                                break;
                            }
                        }
                    }
                    if (isPrime) {
                        System.out.println(i);
                        break;
                    }
                }
            }
        }
    }
}

0개의 댓글