백준 1644번 - 소수의 연속합 (C++, 에라토스테네스의 체, 누적합, 투포인터)
https://www.acmicpc.net/problem/1644
아주 어려운 문제는 아니나, 에라토스테네스의 체, 누적합, 투포인터라는 삼박자를 알고 있어야 풀 수 있는 문제였다.
에라토스테네스의 체 문제를 연속으로 풀다보니 대체 고대 그리스의 철학자들은 얼마나 천재인건가 가늠도 안된다.
아무튼 문제는 다음과 같은 단계로 이루어진다.
1. 에라토스테네스의 체를 사용해 소수 판별
2. 누적합을 통해 각 소수의 범위 prefix 배열 처리
3. 투포인터를 활용해 연속합중 N과 같은 것들 처리
https://tigerfrom2.tistory.com/433
알고리즘 - 에라토스테네스의 체(C++)
최근 코딩테스트에서 소수를 판별해야하는 문제가 나왔다. 그래서 에라토스테네스의 체를 사용해야함을 바로 알았지만 아쉽게 떠올리지 못하여 정리해두려고 한다. 원래 소수를 판별하는 방
tigerfrom2.tistory.com
에라토스네테스의 체 개념
https://tigerfrom2.tistory.com/468
누적합 알고리즘(1차원, 2차원 누적합)
누적합 알고리즘은 1~N까지 합을 효율적으로 구할 수 있는 알고리즘이다. 11 + 21 + 2 + 31 + 2 + 3 + 4 라고하면 sum[1] = 1sum[2] = 3sum[3] = 6sum[4] = 10 이고 여기서 2~4까지의 합을 구하면 sum[4] - sum[1] 과 같
tigerfrom2.tistory.com
누적합의 개념, 누적합은 2차원에서도 사용 가능하다. 카카오 기출문제 중 2차원 누적합이 있어서 이후 대기업들이 충분히 출제할 수 있다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
vector<int> primeNumbers;
int prefix[1000000];
void Eratostenes(int N){
bool check[4000001];
memset(check, false, sizeof check);
check[1] = true;
for(int i = 2; i * i <= N; i++){
if(check[i] == false){
for(int j = i*i; j <= N; j += i){
check[j] = true;
}
}
}
for(int i = 2; i <= N; i++){
if(!check[i]){
primeNumbers.push_back(i);
}
}
}
void makePrefix(){
prefix[0] = 0;
for(int i = 1; i <= primeNumbers.size(); i++){
prefix[i] = primeNumbers[i - 1] + prefix[i - 1];
}
}
int solution(int N){
int answer = 0;
int lo = 0; int hi = 1;
while(hi <= primeNumbers.size()){
int value = prefix[hi] - prefix[lo];
if(value == N){
answer++;
lo++;
hi++;
}else if(value < N){
hi++;
}else if(value > N){
lo++;
}
}
return answer;
}
int main(){
int N; cin >> N;
Eratostenes(N);
makePrefix();
cout << solution(N) << '\n';
}