Home [백준] 2225번 합분해 - Python
Post
Cancel

[백준] 2225번 합분해 - Python

이번에 해결해 볼 문제는 백준에 있는 2225번 합분해입니다.


문제 설명

  1. 0부터 N가지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수를 구하면 됩니다.
  2. 이때 덧셈의 순서가 바뀐 경우는 다른 경우로 세야 합니다.

문제 해결 아이디어

  • $N = 1$인 경우와 $K = 1$인 경우는 경우의 수가 정해져 있습니다.

    • $N = 1$일 때 경우의 수는 $k$개 입니다. ($k \in K$)
    • $K = 1, n = 0$일 때 경우의 수는 1개 입니다. ($n \in N$)

  • $N \ge 2$인 경우와 $K \ge 2$인 경우는 예시와 함께 살펴보겠습니다.

    • $N = 8, K = 5$일 때, 다음과 같이 표기할 수 있습니다.
      • 0이 한 개의 자리를 차지하는 경우 -> [0, 나머지 8이 4개로 나눠지는 경우] == [0, (8, 4)]
      • 1이 한 개의 자리를 차지하는 경우 -> [1, 나머지 7이 4개로 나눠지는 경우] == [1, (7, 4)]
    • 그렇다면 아래와 같이 표시할 수 있습니다.

      • $(8, 5) = [0, (8, 4)] + [1, (7, 4)] + \cdots + [7, (1, 4)] + [8, (0, 4)]$
    • 여기서 중요한 규칙을 발견할 수 있습니다.
      • $(8, 5) = \sum_{i=0}^8[i, (8-i, 4)]$
      • 위의 식을 일반화 하면, $(N, K) = \sum_{i=0}^N[i, (N-i, K-1)]$처럼 표현할 수 있습니다.
    • 위의 식이 직관적이지 않다면 아래와 같이 table 형태로 그릴 수 있습니다.

    • 또한 위의 그림을 아래와 같이 계산 할 수 있습니다.

    • 따라서 $(N, K) = (N-1, K) + (N, K-1)$로 나타낼 수 있으며 아래 그림과 같습니다.

      • (8, 5) = (7, 5) + (8, 4)


문제 해결 코드

위의 아이디어를 종합하면 아래와 같이 코드를 작성할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import sys

input = sys.stdin.readline

N, K = map(int, input().split())

table = [[0 for _ in range(K)] for _ in range(N + 1)]

for i in range(N + 1):
    table[i][0] = 1
for j in range(K):
    table[0][j] = 1
    table[1][j] = j + 1

for i in range(2, N + 1):
    for j in range(1, K):
        table[i][j] = table[i][j - 1] + table[i - 1][j]

print(table[N][K - 1] % 1000000000)

느낀 점

🤔 이번 문제는 약간의 운도 필요했던 것 같습니다. 저 같은 경우 입력의 크기가 크지 않았기 때문에 이를 2차원 행렬로 코드를 구성할 생각을 미리 한 상태에서 문제를 해결 하고자 했습니다. 또한 이렇게 구성된 행렬에서 $(N, K) = (N-1, K) + (N, K-1)$로 정답을 구할 수 있지 않을까 하는 막연한 생각에서 해당 문제를 해결해 나가기 시작했습니다.

🤔 그러나 시작점이 달랐다면 꽤 오랜시간이 걸리거나 해결하지 못했을 것 같습니다. 또한 해당 문제가 만약 코딩 테스트에 출제 된다면 꽤 높은 확률로 정확한 답보다는 “이렇게 하니깐 되네”하면서 해결하고 넘어갈 것 같습니다.

🤔 이러한 문제들을 많이 접하면서 코딩 테스트에 이러한 문제가 출제 되었을 때 당황하는 일이 없도록 해야할 것 같습니다.

This post is licensed under CC BY 4.0 by the author.

[백준] 11052번 카드 구매하기 - Python

[백준] 6588번 골드바흐의 추측 - Python