Study/Algorithm

BOJ (Java) 1644번: 소수의 연속합

hwooo 2025. 4. 22. 14:51

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


풀이

연속된 소수의 합으로 n이 될 수 있는 가능성을 찾는 문제다.

주어진 숫자보다 적은 소수를 다 찾아 해당 값을 리스트에 저장한 후, 해당 리스트를 순회하며 부분합을 구했다.

부분 합 < 주어진 수라면 end 인덱스를 증가하며 부분합에 더하고

부분 합 > 주어진 수라면 start 인덱스를 증가하며 부분합에서 뺐다.

 

이 때 end 인덱스로 끝까지 탐색했을 때 부분 합 > 주어진 수라면 start 인덱스를 증가하며 주어진 수가 소수일 때를 확인했다.


Java 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Main {
    private static List<Integer> primes = new ArrayList<>();
    private static boolean[] nums;
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        int answer = 0;
        int N;
        N = Integer.parseInt(bf.readLine());
        nums = new boolean[N + 1];
        findPrime(N);

        int start = 0;
        int end = 0;
        int size = primes.size();

	// 슬라이딩 윈도우로 탐색
        int sum = 0;
        while (start < size && end < size) {
            if (sum <= N) {
                sum += primes.get(end++);
            } else {
                sum -= primes.get(start++);
            }

            if (sum == N) answer++;
        }
        
        // 모두 탐색 후 주어진 숫자 < 부분합이라면 한 번 더 탐색
        if (N < sum) {
            while (start < size && N < sum) {
                sum -= primes.get(start++);
            }
            if (sum == N)
                answer++;
        }

        System.out.println(answer);
    }

    // 에라토스테네스의 체를 활용, 주어진 범위에서의 소수를 구함
    private static void findPrime(int n) {
        for (int i = 2; i <= n; i++) {
            if (nums[i]) continue;

            primes.add(i);
            for (int j = i; j <= n; j += i) {
                nums[j] = true;
            }
        }
    }
}