※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 14941번 문제인 호기심이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/14941
14941번: 호기심
첫 줄에는 질문의 개수 n이 주어진다. 다음 줄 부터 차례대로 함수의 입력 a, b가 주어진다. (1 ≤ a ≤ b ≤ 105) 또한 남규는 호기심이 많기 때문에 매우 많은 질문을 한다. 따라서 질문의 수 n은 최
www.acmicpc.net
문제에서 주어진 식은 범위 내에서 홀수번째로 등장하는 소수는 3을 곱해 더하고 짝수번째로 등장하는 소수는 -1을 곱해 더하는 형태로 생각할 수 있다.
이러한 계산은 적절한 구간합 전처리를 통해 빠르게 계산해낼 수 있다.
또한 A와 B의 범위가 L = 10만이므로, O(L)의 전처리로 이전 소수와 다음 소수가 무엇인지 O(1)로 접근할 수 있는 배열을 만들 수 있다. (즉, 이분탐색을 구현할 필요가 없다.)
위 둘을 이용해 문제를 간단히 해결하자.
주어진 구간 내에 소수가 존재하지 않거나 하나만 존재해 짝수번째 소수가 존재하지 않는 경우 등의 예외처리에 주의하자.
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
int sieve[101001];
bool isoddprime[101001];
int nextprime[101001], prevprime[101001];
int oddpsum[101001], evenpsum[101001];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
sieve[1] = 1;
for (int i = 2; i * i < 101001; i++) {
if (sieve[i]) continue;
for (int j = i * i; j < 101001; j += i) sieve[j] = 1;
}
int parity = 0;
for (int i = 1; i < 101001; i++) {
if (!sieve[i]) {
parity ^= 1;
if (parity) oddpsum[i] = oddpsum[i - 1] + i, evenpsum[i] = evenpsum[i - 1], isoddprime[i] = 1;
else oddpsum[i] = oddpsum[i - 1], evenpsum[i] = evenpsum[i - 1] + i;
}
else oddpsum[i] = oddpsum[i - 1], evenpsum[i] = evenpsum[i - 1];
}
int tmp = 0;
for (int i = 1; i < 101001; i++) {
prevprime[i] = tmp;
if (!sieve[i]) tmp = i;
}
tmp = 101111;
for (int i = 101000; i > 0; i--) {
nextprime[i] = tmp;
if (!sieve[i]) tmp = i;
}
int Q; cin >> Q;
while (Q--) {
int L, R; cin >> L >> R;
if (sieve[L]) L = nextprime[L];
if (sieve[R]) R = prevprime[R];
int oddL, oddR, evenL, evenR;
if (isoddprime[L]) oddL = L, evenL = nextprime[L];
else oddL = nextprime[L], evenL = L;
if (isoddprime[R]) oddR = R, evenR = prevprime[R];
else oddR = prevprime[R], evenR = R;
if (isoddprime[L]) {
int ans = 0;
if (oddL <= oddR) ans += 3 * (oddpsum[oddR] - oddpsum[oddL] + oddL);
if (evenL <= evenR) ans -= evenpsum[evenR] - evenpsum[evenL] + evenL;
cout << ans << '\n';
}
else {
int ans = 0;
if (evenL <= evenR) ans += 3 * (evenpsum[evenR] - evenpsum[evenL] + evenL);
if (oddL <= oddR) ans -= oddpsum[oddR] - oddpsum[oddL] + oddL;
cout << ans << '\n';
}
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 5624 // C++] 좋은 수 (0) | 2022.06.02 |
---|---|
[BOJ 14942 // C++] 개미 (0) | 2022.06.01 |
[BOJ 5626 // C++] 제단 (0) | 2022.05.30 |
[BOJ 9084 // C++] 동전 (0) | 2022.05.29 |
[BOJ 9047 // C++] 6174 (0) | 2022.05.29 |