문제
1보다 큰 자연수 중에서 1과 자기 자신을 제외한 약수가 없는 자연수를 소수라고 한다. 예를 들어, 5는 1과 5를 제외한 약수가 없기 때문에 소수이다. 하지만, 6은 6 = 2 × 3 이기 때문에 소수가 아니다.
골드바흐의 추측은 유명한 정수론의 미해결 문제로, 2보다 큰 모든 짝수는 두 소수의 합으로 나타낼 수 있다는 것이다. 이러한 수를 골드바흐 수라고 한다. 또, 짝수를 두 소수의 합으로 나타내는 표현을 그 수의 골드바흐 파티션이라고 한다. 예를 들면, 4 = 2 + 2, 6 = 3 + 3, 8 = 3 + 5, 10 = 5 + 5, 12 = 5 + 7, 14 = 3 + 11, 14 = 7 + 7이다. 10000보다 작거나 같은 모든 짝수 n에 대한 골드바흐 파티션은 존재한다.
2보다 큰 짝수 n이 주어졌을 때, n의 골드바흐 파티션을 출력하는 프로그램을 작성하시오. 만약 가능한 n의 골드바흐 파티션이 여러 가지인 경우에는 두 소수의 차이가 가장 작은 것을 출력한다.
풀이
이번 풀이는 pypy3으로 진행되었는데, 그 이유는... python3으로는 시간초과가 계속 발생했기 때문이다. 내 코드로는 도저히 시간이 단축이 안된다... ㅠ
아래는 내가 시도했었던 코드 [python3 : 시간초과] [pypy3 : 통과]
import sys
def goldvagh(n):
prime_factor = eratosthenes(2,n)
goldvagh_number = []
for i in prime_factor[:int(len(prime_factor)/2)+1]:
if n - i in prime_factor and n >= i:
goldvagh_number.append([i,n-i])
min = 10000000
min_gold = 0
if len(goldvagh_number) >= 1:
for i,d in enumerate(goldvagh_number):
if min > (d[1] - d[0]) >= 0:
min = d[1] - d[0]
min_gold = goldvagh_number[i]
return min_gold
else:
return False
def eratosthenes(n, m):
check = [0] * (m + 1)
result = []
for i in range(2, m + 1):
if check[i] == 0:
for j in range(i*2, m + 1, i):
if check[j] == 0:
check[j] = 1
for i in range(n, m+1):
if check[i] == 0:
result.append(i)
if 1 in result:
result.remove(1)
return result
if __name__ == '__main__':
T = int(sys.stdin.readline())
# era = eratosthenes(2,10000)
for _ in range(T):
data = goldvagh(int(sys.stdin.readline()))
if data:
print(data[0], data[1])
다른 분의 코드 아이디어를 참조했다. https://week-year.tistory.com/171
[python] boj 17103 골드바흐 파티션
알고리즘은 꾸준히 풀었는데 글 업로드를 안 했다...정말이다..정말 열심히 풀었다.. 어쨌든 낮은 난이도에 비해 배울 점이 많은 문제라서 이렇게 기록을 남기게 되었다. www.acmicpc.net/problem/17103 17
week-year.tistory.com
- 참고 할 중요 내용은 "단순 반복되는 코드는 꼭 밖에 빼자" python3의 속도를 그나마 높여준다.
- 속도를 항상 최소화 할 수 있는(단순히 코드를 통과하는 게 아닌 것을 목표로) 코드 구조를 구성하자.
import sys
def bj9020_ver2():
prime = [1 for i in range(10001)]
prime[0], prime[1] = 0, 0
num = 2
while num <= int(10001 ** (0.5)):
if prime[num]:
for i in range(num + num, 10001, num):
prime[i] = 0
num += 1
T = int(sys.stdin.readline())
for test in range(T):
n = int(sys.stdin.readline())
for i in range(n//2,1,-1):
if prime[i] and prime[n-i]:
print(i,n-i)
break
bj9020_ver2()
나는 에라토스테네스의 체를 주어진 범위의 최대 (10000)까지 세팅해서 두기도 했었고, 이것을 함수 내부에서 계속 반복한 것 때문에 속도가 조금 느렸던 것 같다.(작은 수는 통과되기도 함 : 최대 9%까지....) T에 따라서 받는 수들의 최대값을 에라토스테네스의 체 세팅을 하고 그 값을 비교할 때도 갯수의 반 까지 만(i = n-i 이기 때문) 계산하는 것.. 기본적인 코딩 규칙으로 생각하자.
'코드연습 > BOJ' 카테고리의 다른 글
BOJ 2447 : 별 찍기 - 10[python3] (0) | 2022.04.18 |
---|---|
BOJ 3053 : 택시 기하학[python3] (0) | 2022.04.15 |
BOJ 4948 : 베르트랑 공준 (0) | 2022.04.14 |
BOJ 1929 : 소수 구하기 (0) | 2022.04.14 |
BOJ 1165 : 소인수 분해 (0) | 2022.04.13 |