[알고리즘 스터디 - 1주차 1] 소수의 연속합
난이도
Gold 3
문제
하나 이상의 연속된 소수의 합으로 나타낼 수 있는 자연수들이 있다. 몇 가지 자연수의 예를 들어 보면 다음과 같다.
- 3 : 3 (한 가지)
- 41 : 2+3+5+7+11+13 = 11+13+17 = 41 (세 가지)
- 53 : 5+7+11+13+17 = 53 (두 가지)
하지만 연속된 소수의 합으로 나타낼 수 없는 자연수들도 있는데, 20이 그 예이다. 7+13을 계산하면 20이 되기는 하나 7과 13이 연속이 아니기에 적합한 표현이 아니다. 또한 한 소수는 반드시 한 번만 덧셈에 사용될 수 있기 때문에, 3+5+5+7과 같은 표현도 적합하지 않다.
자연수가 주어졌을 때, 이 자연수를 연속된 소수의 합으로 나타낼 수 있는 경우의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 4,000,000)
출력
첫째 줄에 자연수 N을 연속된 소수의 합으로 나타낼 수 있는 경우의 수를 출력한다.
예제 입력
20
예제 출력
0
해설 및 후기
소수의 판독은 에라토스테네스의 체를 이용해 시간 내에 풀이할 수 있을 것으로 생각했다. 또한 단순히 소수들의 합이 아닌 연속합이었기 때문에, 투-포인터를 이용해 풀이가 가능할 것으로 생각했다. 우선 n까지의 소수를 모두 뽑은 후, 그 수보다 크거나 같을 때까지 투-포인터의 뒷부분을 증가시키며, 만약 현재 포인터의 합이 더 크다면 투 포인터의 앞부분을 증가시키는 방법으로 계속 진행한다. 만약 값이 같았다면 카운트를 1 증가시킨다.
제출 코드
n = int(input())
tb = [False for _ in range(n+1)]
if(n == 1):
print(0)
exit()
if(n==2):
print(1)
exit()
if(n==5):
print(2)
exit()
pn = []
for i in range(2, int(n**0.5)+1):
c = 2
if(tb[i]):
continue
while(i*c <= n):
tb[i*c] = True
c += 1
for i in range(2, n+1):
if(not tb[i]):
pn.append(i)
start = 0
end = 0
curr = pn[0]
cnt = 0
while(end < len(pn)):
if(curr < n):
end += 1
if(end >= len(pn)):
break
curr += pn[end]
elif(curr > n):
curr -= pn[start]
start += 1
else:
end += 1
if(end == len(pn)):
break
curr += pn[end]
cnt += 1
if(not tb[n]):
cnt += 1
print(cnt)