문제
환상의 나라 디디랜드에서는 인연의 증표로 끈을 하나씩 가지고 있다. 그들은 지극히 평범한 방법으로 이 끈을 이용하여 어떤 두 사람이 환상의 짝꿍인지 판단하는데, 두 사람의 끈을 서로 이어붙이고 그 끈을 다시 길이가 소수인 끈 두개로 정확히 나눌 수 있다면 두 사람은 환상의 짝꿍이라고 한다. 하지만 그들은 길이가 소수인 두개의 끈으로 나눌 수 있는지 판단하는 것이 어려워서 대부분 서로가 인연임을 모르고 그냥 지나간다고 한다. 애석하게도...
그런 그들을 위해서 어떤 두 사람이 환상의 짝꿍인지 판단하는 프로그램을 작성하라.
편의상 두 사람의 끈을 이어붙일 때와 나눌 때 손실되는 끈의 길이는 0이라고 가정한다.
입력
첫째 줄에 테스트 케이스의 수 T(1 ≤ T ≤ 500)가 주어진다.
둘째 줄부터 T개 줄에 두 사람이 가지고 있는 끈의 길이를 나타내는 정수 A, B가 공백으로 구분되어 주어진다. (1 ≤ A, B ≤ 2 × 1012)
출력
각 테스트 케이스마다 한 줄씩 두 사람의 끈을 이어붙이고 그 끈을 다시 길이가 소수인 두개의 끈으로 정확히 나눌 수 있다면 YES, 불가능하면 NO를 출력하라.
코드
#15711
import sys
# 에라토스테네스의 체
# n = 2*(10**12) +1 # 끈의 길이 메모리 초과 따라서 절반만 에라토스테네스의 체 수행
n = 2*(10**6) + 1
arr = [True for _ in range(n)]
primes = [] # 소수
for i in range(2,n):
if arr[i]:
primes.append(i)
for j in range(2*i, n, i):
arr[j] = False
# 소수인지 판별
def isPrime(x):
if x > n: # x 가 n인 2*10**12 보다 크면
for prime in primes:
if prime >= x:
break
elif x % prime == 0:# 소수로 나뉘는지로 판별
return False
return True
else: # x가 n보다 작으면 바로 소수에서 꺼내기
return arr[x]
# 테스트케이스
t = int(sys.stdin.readline())
for _ in range(t):
ab = sum(map(int,sys.stdin.readline().split()))
# 골드바흐의 추측 : 4보다 큰 짝수는 두 홀수 소수의 합으로 가능하다.
# 4 보다 작으면 NO
if ab < 4 :
print("NO")
# 4보다 큰 짝수 YES
elif ab % 2 == 0:
print("YES")
else: # 홀수는 2(짝수 소수) + 홀수 소수의 합으로 가능하다. -> 홀수-2 가 소수인지 확인
if isPrime(ab-2):
print("YES")
else:
print("NO")
풀이
간단하게 에라토스테네스의 체로만 풀면 시간초과 난다.
문제에서 알고 있어야 할 것이 에라토스테네스의 체와 골드바흐의 추측이다.
근데 이렇게 풀어도 python으로는 시간초과가 나서 pypy3로 제출했다.
빠르게 풀 수 있는 방법 아시는분?
1) 체의 범위가 2*10**12나 되기 때문에 그 절반만 에라토스테네스의 체를 우선적으로 만들어주고
소수판별을 원하는 수가 이 범위보다 크면 소수로 나뉘는지로 판별한다.
2) 골드바흐의 추측 : 4보다 큰 짝수는 두 홀수인 소수의 합으로 가능하다.
따라서 4보다 작으면 NO 크면 짝수면 YES
4보다 큰 홀수는 2와 다른 소수 홀수의 합으로 이루어진다.
따라서 홀수-2가 소수인지만 판별하면 된다.
3) 소수인지 판별은 앞서 말했듯 에라토스테네스의 체 범위보다 크면 소수로 나눈다. 나누어지면 소수가 아니다.
그 범위보다 작으면 바로 에라토스테네스의 체로 구해놓은 소수배열에서 꺼내쓴다.
'알고리즘 문제 풀이 > 백준' 카테고리의 다른 글
[백준] 7569 토마토 python (0) | 2022.03.09 |
---|---|
[백준] 7576 토마토 python (0) | 2022.03.09 |
[백준] 11053 가장 긴 증가하는 부분 수열 python (0) | 2022.03.09 |
[백준] 2156 포도주 시식 python (0) | 2022.03.09 |
[백준] 1655 가운데를 말해요 python (*) (0) | 2022.03.06 |