백준 17103. 골드바흐 파티션
알고리즘 기초 문제 중 수학1 연습 문제(301)
1. 간단 설명
골드바흐의 추측: 2보다 큰 짝수는 두 소수의 합으로 나타낼 수 있다
짝수 N을 두 소수의 합으로 나타내는 표현을 “골드바흐 파티션”이라고 한다
짝수 N이 주어졌을 때, 골드바흐 파티션의 개수를 구하는 문제
2. 문제 분석
두 소수의 순서만 다른 것은 같은 파티션으로 취급한다
즉 8의 골드파흐 파티션인 [3,5]과 [5,3]은 같은 파티션으로 취급한다
예시
1
2
3
4
5
6
5
6
8
10
12
100
입력이 주어졌을 때
1
2
3
4
5
6 : [3+3] 1개
8 : [3+5] 1개 ([5+3]과 같음)
10 : [3+7], [5+5] 1개
12 : [5+7] 1개
100 : [3+97], [11+89], [17+83], [29+71], [41+59], [47+53] 6개
풀이
- 테스트케이스별로 일일히 소수를 구하는것은 비효율적이라 생각하여 에라토스테네스의 체를 이용하여 소수를 구함
- 순서가 다른것은 같은 파티션이므로, 수의 절반까지만 확인하면 된다(n이 최대 100만이므로, 50만까지만 확인)
필요 변수
- 테스트 케이스 개수 T (1<= T <= 100)
- 에라토스테네스의 체를 이용하여 소수를 판별
grid[100만]
- 입력 정수
int n
(최대 100만) - 파티션의 개수
int cnt
주의사항
- 6 = [3+3]처럼 같은 소수가 중복되어 사용되어도 상관없음
- 시간 제한이 0.5초이므로, 약 5억번 수행 가능
알고리즘
1
2
3
4
5
6
7
8
1. 에라토스테네스의 체를 초기화한다
2. TC 개수 T입력받기
3. 각 TC에 대하여 아래 작업 수행
3-1. N 입력받기
3-2. 2부터 n/2까지 소수를 찾고, n에서 해당 소수를 뺀 값이 소수인지 확인한다
3-3. 두 값이 소수가 맞다면 카운트 증가
3-4. 카운트 출력
4. 종료
3. 소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <memory.h>
using namespace std;
bool grid[1000001];
void init_grid() {
memset(grid, 1, sizeof(grid));
grid[0] = 0;
grid[1] = 0;
for (int i = 2; i <= 1000; i++) { // sqrt(100,0000)
if (grid[i] == false) continue;
for (int j = i*2; j <= 1000000; j = j + i) {
grid[j] = false;
}
}
}
int main() {
freopen_s(new FILE*, "input.txt", "r", stdin);
int T, n;
init_grid();
cin >> T;
while (T--) {
cin >> n;
int cnt = 0;
for (int i = 2; i <= n/2; i++) {
if (grid[i] == true && grid[n - i] == true) cnt++;
}
cout << cnt << '\n';
}
return 0;
}
시간 제한이 0.5초라서 에라토스테네스의 체를 초기화 하는 과정에서 시간 초과가 나지 않을까 잠깐 고민했다.
그러나, 이전에 풀었던 소수인 펠린드롬 문제에서 배웠던
‘에라토스테네스의 체 혹은 소수판정 시 제곱근 까지만 확인하면 된다’는 사실을 기억했다.
i를 100만번이 아닌 제곱근인 1000번만 수행하여 시간을 2배 이상 단축할 수 있었고,
실제 측정해본 결과 성능에 따라 다르겠지만 시간 내 들어오는 것을 확인할 수 있었다
또한, 메모리 효율을 위해 체를 int형이 아닌 bool형을 사용했음
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.