algorithm/DP

[백준11057/실버1] 오르막 수 - Python

ayeongjin 2025. 2. 4. 22:00

https://www.acmicpc.net/problem/11057

 

첨엔 문제가 이해 안됐다.

수의 길이 N은 N자리수 수 중에 오르막 수를 구하라는 뜻이었다.

 

그래서 dp 배열을 10 * (N+1) 칸으로 만들었다.

그리고 dp[i][j] = i 자리 수 중에 첫번째 숫자가 j인 수의 오르막 수로 지정해서 풀었다.

 

1. 

한자리 수 중에 첫자리가 0인 수의 오르막 수 = 0개

한자리 수 중에 첫자리가 1인 수의 오르막 수 = 1개

한자리 수 중에 첫자리가 2인 수의 오르막 수 = 1개

...

한자리 수 중에 첫자리가 9인 수의 오르막 수 = 1개

이므로 dp[1] = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1] 로 초기화했다.

 

2. 

두자리 수 중에 첫자리가 1인 수의 오르막 수 = 한자리 수 중에 첫자리가 1~9로 시작하는 오르막수

두자리 수 중에 첫자리가 2인 수의 오르막 수 = 한자리 수 중에 첫자리가 2~9로 시작하는 오르막수

두자리 수 중에 첫자리가 3인 수의 오르막 수 = 한자리 수 중에 첫자리가 3~9로 시작하는 오르막수

...

두자리 수 중에 첫자리가 1인 수의 오르막 수 = 한자리 수 중에 첫자리가 1~9로 시작하는 오르막수

이므로

for i in range(2, N+1):
    for j in range(10):
        dp[i][j] = (sum(dp[i-1][j:])) % 10007

이렇게 dp 배열을 순회했다.

 

 

# 성공 코드 1

N = int(input())

dp = [[0] * 10 for _ in range(N+1)] # dp[i][j] : i자리수에서 첫 숫자가 j인 오르막 개수

dp[1] = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1]

for i in range(2, N+1):
    for j in range(10):
        dp[i][j] = (sum(dp[i-1][j:])) % 10007

print((sum(dp[N]) + 1) % 10007)

 

위의 코드도 for문 안에서만 % 10007 해주고

최종 결과 출력에는 print(sum(dp[N]) + 1) 이렇게 10007로 안나눠줘서 엄청 틀렸다.

 

근데 코드가 보다보니까 dp[i][j] = dp[i-1][j] + dp[i][j-1] 로 이루어져서 누적합으로 변경할 수 있을 거같아서 리팩토링했다.

 

# 성공 코드 2

N = int(input())

dp = [[0] * 10 for _ in range(N+1)] # dp[i][j] : i자리수에서 첫 숫자가 j인 오르막 개수

dp[1] = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1]

for i in range(2, N+1):

    # 누적합으로 변경
    dp[i][9] = dp[i-1][9]
    for j in range(8, -1, -1):
        dp[i][j] = (dp[i-1][j] + dp[i][j+1]) % 10007

print((sum(dp[N]) + 1) % 10007)