백준 2225번 합분해

Baekjoon algorithm

Posted by kwon on 2020-02-14

Problem 2225

합분해

문제

0부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수를 구하는 프로그램을 작성하시오.

덧셈의 순서가 바뀐 경우는 다른 경우로 센다(1+2와 2+1은 서로 다른 경우). 또한 한 개의 수를 여러 번 쓸 수도 있다.

입력

첫째 줄에 두 정수 N(1 ≤ N ≤ 200), K(1 ≤ K ≤ 200)가 주어진다.

출력

첫째 줄에 답을 1,000,000,000으로 나눈 나머지를 출력한다.

문제 링크

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

예제 입력 1

20 2

예제 출력 1

21

solve

  • 점화식 d[k][N] = 0부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수
  • o + o + o + … + L = N –> L 의 자리에 올 수 있는 수 : 0 ~ N
    • [ N - L ] + L = N
    • [ k - 1개 ] + 1개 = k
      - 따라서, d[k - 1][n - L]의 모든 경우에 L을 더해주면 d[k][n]을 구할 수 있다.
        - 즉, d[k - 1][n - L]의 모든 경우를 합친 수가 d[k][n]의 경우의 수가 되는 것이다.
  • d[k][n] = sum(d[k - 1][n - L])
    • 0 <= L <= N

코드 설명

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#include <iostream>

using namespace std;
long long d[201][201];
long long mod = 1000000000;
int main(void)
{
int n, k; // n이하의 정수 k개를 더해 n을 만드는 경우의 수
cin >> n >> k;

for (int i = 0; i <= n; i++) // 1개의 정수로 n을 만드는 경우는 모두 1
d[1][i] = 1; // 초기값 설정

for (int i = 1; i <= k; i++)
for (int j = 0; j <= n; j++)
for (int l = 0; l <= j; l++)
{
d[i][j] += d[i - 1][j - l]; // d[k][n] = sum(d[k - 1][n - L])
d[i][j] %= mod;
}

cout << d[k][n] << '\n';

}