백준 11057번 - 오르막 수
오르막 수 문제 바로 가기
풀이 날짜: 2026-01-12
baekjoon 알고리즘 문제 풀이
풀이 코드
import sys
input = sys.stdin.readline
n = int(input())
dp = list([0]*10 for _ in range(n+1))
dp[1] = [1] * 10
for i in range(2,n+1):
for j in range(10):
if j==0:
dp[i][j] = 1
else:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
print(sum(dp[n]) % 10007)
문제 접근
이 문제는 길이가n인 “오르막 수(자리수가 줄어들지 않는 수)”의 개수를 구하는 문제라서, 한 자리씩 늘려가며 경우의 수를 누적하는 방식이 자연스럽다.
어떤 수가 오르막이 되려면 마지막 자릿값이 정해졌을 때 그 이전 자리들이 만들 수 있는 경우의 수로 계산할 수 있기 때문에, “길이”와 “마지막 숫자”를 상태로 두는 DP로 풀 수 있다.
DP 정의
- dp[i][j] = 길이가 i이고 마지막 숫자가 j인 오르막 수의 개수.
헷갈렸던 점 정리
초기값이 왜 dp[1] = [1]*10 인지
길이가 1인 수는 0~9 각각이 그 자체로 오르막 수이기 때문에, 마지막 숫자가 0이든 9든 가능한 수는 딱 1개씩 존재한다.
그래서 dp[1][0..9] = 1 이 되고, 코드로는 dp[1] = [1] * 10이 되는 것이다.
반대로 dp[0]은 길이가 0이기 때문에 (= 아무 숫자도 없는 상태), 문제에서 실제 숫자로 쓰이지 않고, 이 풀이에서는 굳이 사용할 필요가 없기 때문에 초기 시작을 dp[1]로 했다.
최종 답이 sum(dp[n]) 인 이유
우리가 구하고 싶은 건 길이 n인 오르막 수의 “전체 개수”다. 그런데 DP는 “마지막 숫자별 개수”로 나뉘어 있으니, 길이 n에서 마지막 숫자가 0~9인 경우를 모두 더하면 전체가 된다. 그래서 답은 sum(dp[n])이고, 마지막에 문제 조건에 따라 10007로 나눈 나머지를 출력한다.