문제 설명


문제

정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 3가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. 단, 같은 수를 두 번 이상 연속해서 사용하면 안 된다.

  • 1+2+1
  • 1+3
  • 3+1

정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 100,000보다 작거나 같다.

출력

각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.


풀이 과정

  1. DP 테이블을 구성한다
    • DP[i][j] : i를 합으로 나타낼 때, 맨 마지막에 사용할 수가 j
  2. DP 테이블의 값을 미리 모두 채워둔다.
    • 최대 N이 100000이므로 100000개 모두 미리 채워둔다.
    • DP[i][1]의 값은 DP[i-2][2] + DP[i-3][3] 이러한 식으로 채워줌.
      • 이유는, 1을 사용하기 위해서는 이전에 2 또는 3이 나타나야 하기 때문.
  • 어려웠던 점
    1. DP 테이블을 2차원으로 구성해야 되는 점 생각이 어려웠음..
    2. DP 테이블을 반복문에서 매번 초기화해줘서 시간 초과가 나타났는데, 이 점을 맨 위에서 모두 채워주고 아래에서 테스트 케이스를 입력받을 때, 대응되는 값을 바로바로 출력하도록 바꾸어 줌.

소스 코드


import sys

input = sys.stdin.readline
T = int(input().rstrip())

# dp[i][j] : i번째에 마지막으로 숫자가 j인 경우
dp = [[0, 1, 1, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 1, 1]] + (
    [[0] * 4 for _ in range(100001)]
)

for i in range(4, 100001):
    for j in [1, 2, 3]:
        for k in range(1, 4):
            # 이전에 나온 숫자를 바로 다시 나오게 하면 안됨.
            if j != k:
                dp[i][j] = (dp[i][j] + dp[i-j][k]) % 1000000009

for _ in range(T):
    n = int(input().rstrip())
    print(sum(dp[n]) % 1000000009)

+ Recent posts