coding skill
[백준][문제 풀기] 알고리즘 기초 1/2 - 6588 골드바흐의 추측
pikabite
2022. 3. 23. 15:33
이번 문제에서 물어보는 것은 세가지이다.
얼마나 불필요한 코드를 잘 제거하는지
에라토스테네스의 채를 알고 있고 구현 할 수 있는지
게다가 시간제한이 꽤나 까다롭다
거두절미하고 바로 코드로 들어가자
"""
백준 6588 골드바흐의 추측
"""
import sys
def is_prime (num) :
if num < 2 : return False
for i in range(2, num) :
if num%i == 0 :
return False
return True
if __name__ == "__main__" :
while True :
# 데이터를 잘 받자!
num = int(sys.stdin.readline().strip())
if num == 0 : break
primes_odd = []
for i in range(num) :
if is_prime(i) and i%2 == 1 : primes_odd.append(i)
for v in primes_odd :
is_find = False
for vv in primes_odd :
if v == vv : continue
if v + vv == num :
if v > vv :
tmp = v
v = vv
vv = tmp
print(f"{num} = {v} + {vv}")
is_find = True
break
if is_find : break
if not is_find : print("Goldbach's conjecture is wrong")
실패 한 코드
- 일단 첫 시도는 의식이 흐르는대로 진행했다
- 타겟이 되는 숫자를 받음 -> 이하 소수들을 모음 -> 각각의 소수를 더했을 때 타겟 한 숫자인지 체크 -> 작은 수를 앞에 두고 print, break
- 역시나 예상대로 시간초과가 뜬다
"""
백준 6588 골드바흐의 추측
"""
import sys
def is_prime (num) :
if num < 2 : return False
for i in range(2, int(num**0.5)) :
if num%i == 0 :
return False
return True
if __name__ == "__main__" :
primes_odd = [False] * 10000
for i in range(10000) :
if is_prime(i) and i%2 == 1 :
primes_odd[i] = True
while True :
# 데이터를 잘 받자!
num = int(sys.stdin.readline().strip())
if num == 0 : break
a = num//2
b = num//2
find = False
for i in range(10000//2) :
if a < 2 or b > 10000 : break
if not primes_odd[a] :
a -= 1
continue
if not primes_odd[b] :
b += 1
continue
if a + b == num :
print(f"{num} = {a} + {b}")
find = True
break
if not find : print("Goldbach's conjecture is wrong")
역시 실패 한 코드
- 무수히 많은 시도들 중 또 다른 시도
- list에 append 하고 in으로 찾던 소수목록을 타겟 number 받기 전에 미리 만듦
- a와 b를 설정하고 중앙에서부터 바깥으로 찾아가도록 변경
- 소수를 찾는 과정에서 n이 아닌 n의 제곱근 사용
- 했지만 여전히 시간초과다
"""
백준 6588 골드바흐의 추측
"""
import sys
MAXVAL = 100002
def find_primes () :
primes = [True] * MAXVAL
primes[0] = False
primes[1] = False
for i in range(2, int(MAXVAL**0.5)+1) :
for ii in range(i*2, MAXVAL, i) :
primes[ii] = False
return primes
if __name__ == "__main__" :
primes = find_primes()
while True :
# 데이터를 잘 받자!
num = int(sys.stdin.readline().strip())
if num == 0 : break
a = num - 3
b = 3
find = False
while b <= a :
if not primes[a] :
a -= 1
continue
if not primes[b] :
b += 1
continue
if a + b == num :
print(f"{num} = {a} + {b}")
find = True
break
else :
a -= 1
b += 1
if not find : print("Goldbach's conjecture is wrong")
역시 실패 한 코드
- 이 코드 또한 시간초과가 뜬다.
- 이 경우 에라토스테네스의 채를 사용했는데도 마찬가지였다.
"""
백준 6588 골드바흐의 추측
"""
import sys
MAXVAL = 1000002
def find_primes () :
primes = [True] * MAXVAL
primes[0] = False
primes[1] = False
for i in range(2, int(MAXVAL**0.5)+1) :
for ii in range(i*2, MAXVAL, i) :
primes[ii] = False
return primes
if __name__ == "__main__" :
primes = find_primes()
while True :
# 데이터를 잘 받자!
num = int(sys.stdin.readline().strip())
if num == 0 : break
a = 3
b = num - 3
find = False
while a <= b :
if not primes[a] or not primes[num-a] :
a += 1
continue
# if not primes[b] :
# b -= 1
# continue
b = num-a
if a + b == num :
print(f"{num} = {a} + {b}")
find = True
break
else :
a += 1
b -= 1
if not find : print("Goldbach's conjecture is wrong")
정답 코드
- 직전 코드와 다른 점은 b, a를 구할 때 a값이 소수인지를 구하고, b값을 n-a로하여 소수인지를 구한다는 점이다
- 둘 사이의 시간복잡도는 정확히 계산 하기는 어려울것
- a가 소수인지 판단 -> b가 소수인지 판단 -> a+b=n인지 판단
- a가 소수인지 판단 -> a+b=n을 갖는 b가 소수인지 판단
- 위 케이스와 비교 할 때 계산량이 분명히 적어진다는 장점이 있는 것 같다
- 대략 n과 2n 정도의 복잡도 차이일 것으로 판단된다
- 이정도까지 요구한다는 것은 이 문제가 (내기준)상당히 까다로운 문제인 것 같다