[알고리즘 스터디 - 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)