[JAVA] 백준 (골드5) 2023번 신기한 소수

AIR·2024년 5월 3일
0

링크

https://www.acmicpc.net/problem/2023


문제 설명

정답률 45.860%
수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다.

7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수이고, 7도 소수이다. 즉, 왼쪽부터 1자리, 2자리, 3자리, 4자리 수 모두 소수이다! 수빈이는 이런 숫자를 신기한 소수라고 이름 붙였다.

수빈이는 N자리의 숫자 중에서 어떤 수들이 신기한 소수인지 궁금해졌다. N이 주어졌을 때, 수빈이를 위해 N자리 신기한 소수를 모두 찾아보자.


입력 예제

  • 첫째 줄에 N(1 ≤ N ≤ 8)이 주어진다.

4


출력 예제

  • N자리 수 중에서 신기한 소수를 오름차순으로 정렬해서 한 줄에 하나씩 출력한다.

2333
2339
2393
2399
2939
3119
3137
3733
3739
3793
3797
5939
7193
7331
7333
7393


풀이

단순히 소수를 찾는 문제가 아니라 왼쪽에서 따졌을 때 자릿수마다 모두 소수여야 한다. 첫째 자리부터 마지막 자리까지 소수인지 탐색을 해야하므로 DFS를 이용한다.

우선 첫째 자리가 소수이려면 2, 3, 5, 7이므로 이 숫자들 부터 탐색을 한다. 그리고 둘째 자리부터도 소수여야 하므로 짝수는 될 수 없으므로 1, 3, 5, 7, 9에 대해서만 탐색한다. DFS를 반복하면서 N의 자릿수일 때 소수인 수를 출력한다.

가령 2를 탐색하고 있다면 다음과 같이 탐색하면서 소수를 찾아 나간다.

  • 2
    • 21
    • 23
      • 231
      • 233
        • 2331
          ...
      • 235
      • 237
      • 239
    • 25
    • 27
    • 29
      ...

단 보통 소수를 판단할 때는 에라토스테네스의 체를 사용하지만 여기서 사용하면 메모리 초과가 발생한다. 애초에 첫째 자리가 2, 3, 5, 7로 시작하고 탐색하는 경우의 수가 극단적으로 줄어가므로 에라토스테네스의 체로 미리 소수를 구해놓는 것보다 각 경우마다 소수인지 판단하는 것이 메모리나 시간이 절약된다.

코드

//백준
public class Main {

    private static int N;

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

        System.setIn(new FileInputStream("src/input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());
        int[] primeNumbers = {2, 3, 5, 7};
        for (int primeNumber : primeNumbers) {
            dfs(primeNumber, 1);
        }

    }

    static void dfs(int num, int len) {
        //길이가 N일 때 출력
        if (len == N) {
            System.out.println(num);
            return;
        }

        int[] oddNumbers = {1, 3, 5, 7, 9};
        for (int oddNumber : oddNumbers) {
            //현 숫자의 일의 자리에 홀수를 추가
            int cur = num * 10 + oddNumber;
            //추가한 수가 홀수이면 재귀 호출
            if (isPrime(cur)) {
                dfs(cur, len + 1);
            }
        }
    }

    //소수 판단 메서드
    static boolean isPrime(int number) {
        for (int i = 2; i * i <= number; i++) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }

}

참고

소수 구하기

profile
백엔드

0개의 댓글