https://www.acmicpc.net/problem/6588
6588번: 골드바흐의 추측
각 테스트 케이스에 대해서, n = a + b 형태로 출력한다. 이때, a와 b는 홀수 소수이다. 숫자와 연산자는 공백 하나로 구분되어져 있다. 만약, n을 만들 수 있는 방법이 여러 가지라면, b-a가 가장 큰
www.acmicpc.net
문제
1742년, 독일의 아마추어 수학가 크리스티안 골드바흐는 레온하르트 오일러에게 다음과 같은 추측을 제안하는 편지를 보냈다.
4보다 큰 모든 짝수는 두 홀수 소수의 합으로 나타낼 수 있다.
예를 들어 8은 3 + 5로 나타낼 수 있고, 3과 5는 모두 홀수인 소수이다. 또, 20 = 3 + 17 = 7 + 13, 42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23이다.
이 추측은 아직도 해결되지 않은 문제이다.
백만 이하의 모든 짝수에 대해서, 이 추측을 검증하는 프로그램을 작성하시오.
입력
입력은 하나 또는 그 이상의 테스트 케이스로 이루어져 있다. 테스트 케이스의 개수는 100,000개를 넘지 않는다.
각 테스트 케이스는 짝수 정수 n 하나로 이루어져 있다. (6 ≤ n ≤ 1000000)
입력의 마지막 줄에는 0이 하나 주어진다.
출력
각 테스트 케이스에 대해서, n = a + b 형태로 출력한다. 이때, a와 b는 홀수 소수이다. 숫자와 연산자는 공백 하나로 구분되어 있다. 만약, n을 만들 수 있는 방법이 여러 가지라면, b-a가 가장 큰 것을 출력한다. 또, 두 홀수 소수의 합으로 n을 나타낼 수 없는 경우에는 "Goldbach's conjecture is wrong."을 출력한다.

💻 코드
import sys
prime_list = [True for i in range(1000001)]
for i in range(2, int(1000000**0.5) + 1):
for j in range(i + i, 1000001, i):
prime_list[j] = False
while True:
n = int(sys.stdin.readline())
if (n == 0):
break
for i in range(3, len(prime_list)):
if prime_list[i] and prime_list[n - i]:
print(n, "=", i, "+", n - i)
break
📝 풀이
이 문제는 이전에 풀었던 소수 구하기 문제에서 응용된 버전으로, 입력한 짝수를 두 홀수 소수의 합으로 나타내는 문제이다. 처음에는 1929번 소수 구하기 문제에 작성한 함수를 가져와 소수 리스트를 만들어 리스트를 탐색하며 두 홀수 소수의 합을 찾아내는 방식으로 풀었는데 역시나 시간 초과가 걸렸다. 이 문제를 해결하기 위해서는 소수를 구하는 방법을 바꿔야 했다. 소수를 찾는 알고리즘인 에라토스테네스의 체를 이용하여 풀어서 해결했다.
에라토스테네스의 체란?
소수를 찾는 알고리즘으로 순서는 다음과 같다.
- 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다. 그림에서 회색 사각형으로 두른 수들이 여기에 해당한다.
- 2는 소수이므로 오른쪽에 2를 쓴다. (빨간색)
- 자기 자신을 제외한 2의 배수를 모두 지운다.
- 남아있는 수 가운데 3은 소수이므로 오른쪽에 3을 쓴다. (초록색)
- 자기 자신을 제외한 3의 배수를 모두 지운다.
- 남아있는 수 가운데 5는 소수이므로 오른쪽에 5를 쓴다. (파란색)
- 자기 자신을 제외한 5의 배수를 모두 지운다.
- 남아있는 수 가운데 7은 소수이므로 오른쪽에 7을 쓴다. (노란색)
- 자기 자신을 제외한 7의 배수를 모두 지운다.
- 위의 과정을 반복하면 구하는 구간의 모든 소수가 남는다.

↓ 에라토스테네스의 체를 이용하여 소수 찾는 알고리즘 구현하기
prime_list = [True for i in range(1000001)]
for i in range(2, int(1000000**0.5) + 1):
for j in range(i + i, 1000001, i):
prime_list[j] = False
시간 복잡도를 줄이기 위해서 입력하는 숫자마다 소수를 구하지 않고 미리 최대 입력 케이스인 1000000까지의 소수 리스트를 만들어두고 이 리스트를 활용해야한다. 소수를 찾을 때는 앞서 말했던 에라토스테네스의 체를 이용하여 for문을 통해 i번째일 때 자기 자신 i를 제외한 i의 배수들의 인덱스를 모두 false로 만들면서 이를 반복하고, 1000000까지 돌면 남은 True 값을 가진 인덱스는 소수 리스트가 된다. 이 리스트를 이용하여 형식에 맞게 출력하면 된다.
다음은 이 문제를 풀면서 코드를 이해하기 위해 필기했던 노트이다. (글씨를 좀 날려적은 것 같긴하지만 참고용으로 올려둔다.)

※ 참고
에라토스테네스의 체 - 위키백과, 우리 모두의 백과사전
ko.wikipedia.org
'Algorithm 문제 풀이 > python' 카테고리의 다른 글
[python] 백준 11726번 2 X n 타일링 문제 풀이 (0) | 2022.07.12 |
---|---|
[python] 백준 1463번 1로 만들기 문제 풀이 (0) | 2022.06.25 |
[python] 백준 1929번 소수 구하기 (0) | 2022.06.21 |
[python] 백준 2609번 최대공약수와 최소공배수 문제 풀이 (0) | 2022.06.21 |
[python] 백준 9012번 괄호 문제 풀이 (0) | 2022.06.17 |