1+ """
2+ 풀이 시간: 22분
3+
4+ <input>
5+ t: 테스트케이스
6+ n: 찾아야 하는 골드바흐 파티션의 합이 되는 짝수(4 ≤ n ≤ 10,000)
7+
8+ <solution>
9+ 합이 n이 되는 짝수를 어떻게 찾을 수 있을까?
10+ - 2 ~ 최대 10,000개까지의 소수 중 합이 n이 되게 하는 두 소수를 찾기 위해서 투포인터를 사용할 수 있다.
11+ - 소수가 정렬돼있는 상태이기 때문에 left는 시작 인덱스, right은 끝 인덱스로 초기화 후, 두 소수의 합을 계속해서 target과 비교하며 포인터를 이동시킨다.
12+
13+ <시간복잡도>
14+ O(nlog(logn)): 에라토스테네스의체
15+ find_parition 함수는 최대 O(n)
16+
17+
18+ 뭔가 더 최적화할 수 있는 방법이 있을 것 같은데 생각이 안남.... 여러분의 신박한 풀이 기다립니다..
19+ """
20+
21+ import sys
22+ input = sys .stdin .readline
23+ from typing import List
24+
25+ def find_prime_numbers (mx : int ) -> List :
26+ """
27+ mx: 2 ~ mx까지 중 소수인 수
28+ """
29+ arr = [True ] * (mx + 1 )
30+ arr [0 ] = arr [1 ] = False # 0과 1은 소수가 아님
31+
32+ # 에라토스테네스의 체
33+ for i in range (2 , int (mx ** (1 / 2 ))+ 1 ):
34+ if arr [i ]: # i가 소수인 경우
35+ j = 2
36+ while i * j <= mx :
37+ arr [i * j ] = False
38+ j += 1
39+
40+ return [i for i in range (len (arr )) if arr [i ]]
41+
42+
43+ def find_partition (target : int , prime_number : List ) -> List :
44+ """
45+ target: 찾아야 하는 골드바흐 파티션의 합이 되는 짝수
46+ prime_number: n까지의 소수 배열
47+ """
48+ left , right = 0 , len (prime_number )- 1
49+ diff = target # 현재까지 찾은 최소 차이
50+ result = [0 , 0 ] # 최소 차이를 가지는 골드바흐 파티션
51+
52+ # 투포인터
53+ while left <= right :
54+ cur_sum = prime_number [left ] + prime_number [right ]
55+ if cur_sum == target : # 두 소수의 합이 target이 될 때
56+ if diff > prime_number [right ] - prime_number [left ]: # 최소 차이 업데이트
57+ diff = prime_number [right ] - prime_number [left ]
58+ result [0 ], result [1 ] = prime_number [left ], prime_number [right ]
59+ left += 1
60+ elif cur_sum < target : # 두 소수의 합이 target보다 작다면 left를 증가
61+ left += 1
62+ else : # 두 소수의 합이 target보다 크다면 right를 감소
63+ right -= 1
64+ return result
65+
66+ # 테스트 케이스의 수
67+ t = int (input ())
68+ primes = find_prime_numbers (10000 ) # 입력으로 들어올 수 있는 가장 큰 n은 10,000이기 때문에 미리 10,000까지 모든 소수를 구해둠
69+ for _ in range (t ):
70+ n = int (input ())
71+ print (* find_partition (n , primes ))
0 commit comments