백준 1644 - 소수의 연속합 (Python3)
코드
n = int(input())
# 소수 찾기 메소드
# 에라토스테네스의 체 활용
def find_prime(n):
check = [False for _ in range(n+1)]
# 소수를 담을 리스트
prime = []
for i in range(2, n+1):
# False인 경우에만 prime에 담음
# 사실상 반복문 내에서 i는 소수
if check[i] == False:
prime.append(i)
# j는 i의 배수로 이루어져 있음 => 절대 소수일 수 없음 => True로 변경
for j in range(i, n+1, i):
check[j] = True
return prime
# 부분합을 연산 메소드
def two_pointer(arr):
cnt = 0
start = 0
end = 0
while end <= len(arr):
tmp = sum(arr[start:end])
# n과 부분합이 같으면
# 개수를 1 증가
# start, end 모두 1씩 증가
if tmp == n:
cnt += 1
end +=1
start += 1
# n보다 부분합이 작으면
# end 1 증가
# => 부분 수열의 길이가 1 증가하므로 값이 더 커짐 (주어진 arr에 있는, 부분 수열에 포함된 맨 마지막 요소의 그 다음 요소)
# => n보다 값을 크게 하거나 같아짐을 기대할 수 있음
elif tmp < n:
end += 1
# n보다 부분합이 크면
# start 1 증가
# => 부분 수열의 길이가 1 감소하므로 값이 더 작아짐 (기존 맨 앞의 요소)
# => n보다 값을 작게 하거나 같아짐을 기대할 수 있음
else:
start += 1
return cnt
prime_list = find_prime(n)
answer = two_pointer(prime_list)
print(answer)
문제 해설
에라토스테네스의 체와 투 포인터를 활용하여 풀 수 있는 문제.
특정 숫자를 그보다 작은 소수로 표현할 수 있는 경우의 수를 구하는 문제이다.
문제 풀이 순서는 아래와 같다.
- 에라토스테네스의 체를 활용하여 주어지는 숫자 n보다 작은 소수들로 이루어진 리스트를 생성
- 얻은 리스트에 투 포인터 알고리즘을 활용하여 연속된 소수의 합이 n인 경우의 수를 반환
에라토스테네스의 체를 이용하는 방법을 알지 못한다면 시간 초과가 발생할 수 있는 문제이며 그 이외의 부분은 흔한 투 포인트 문제와 별 차이가 없다. 소수 판별 로직에대한 참고는 나무위키의 설명이 매우 잘 되어있다.
댓글남기기