문제
https://www.acmicpc.net/problem/1644
풀이
import java.io.*;
import java.util.*;
public class Main {
static int n;
static boolean[] isPrime;
static ArrayList<Integer> primeList = new ArrayList<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
isPrime_fun(n);
int start = 0, end = 0, sum = 0, answer = 0;
for(int i = 0; i < isPrime.length; i++){
if(isPrime[i]){
primeList.add(i);
}
}
while(true){
if(sum >= n){ // 원하는 값보다 커지는 경우에 대한 처리
sum -= primeList.get(start++); // 제일 앞의 인덱스에 대한 값 감소 후 인덱스 증가
}else if(end == primeList.size()){ // 만약 더 이상 더할 것은 없는데, sum 마저 n보다 크거나 같지 못하다면 종료
break;
}else{
sum += primeList.get(end++); // 원하는 값보다 작다면 제일 끝의 인덱스에 대한 값 증가 후 인덱스 증가
}
if(sum == n){
answer++; // 동일하다면 정답 + 1
}
}
System.out.println(answer);
}
static void isPrime_fun(int n){
isPrime = new boolean[n+1]; // N번째의 수 까지 받기위해 N+1까지 동적할당
for(int i = 0; i < isPrime.length; i++){
isPrime[i] = true; // boolean배열의 default값은 false이므로 true로 바꿔주기
}
isPrime[0] = isPrime[1] = false; // 0과 1은 소수가 아니니깐 false
// System.out.println(n);
for(int i = 2; i <= Math.sqrt(n); i++){ // 2부터 n의 제곱근까지의 모든 수를 확인
if(isPrime[i]){ // 해당수가 소수라면, 해당수를 제외한 배수들을 모두 false 처리하기
for(int j = i*i; j<= n; j += i){//그 이하의 수는 모두 검사했으므로 i*i부터 시작
isPrime[j] = false;
}
}
}
} // isPrime_fun 함수 종료
}
문제 난이도가 어렵다기보다는 적절한 두가지의 알고리즘을 얼마나 잘 사용할 수 있냐라는 것이 중요한 것 같다.
사용한 알고리즘은 1. 에라토스테네스의 채로 연속된 소수의 리스트를 먼저 구한 뒤, 2. 투포인터 알고리즘으로 정답을 효율적으로 찾는 것이다.
'문제 풀이 > 백준' 카테고리의 다른 글
[백준]11660번. 구간 합 구하기5(JAVA) (1) | 2024.10.09 |
---|---|
[백준] 16953번. A -> B(JAVA) (0) | 2024.10.08 |
[백준]12852번. 1로 만들기 2(JAVA) (0) | 2024.10.02 |
[백준]2632번. 피자 판매(JAVA) (2) | 2024.10.01 |
[백준]2668번. 숫자 고르기(JAVA) (0) | 2024.09.30 |