본문 바로가기
PS

백준 2225번 C++ 합분해

by mtoc 2019. 6. 2.


합분해

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

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

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





생각하는 과정

아직도 dp를 잘 못 이해하고 있었던 건지 ㅠㅠ 이상하게 풀려고 했었다.

끄적거리다가 맥도날드가 시끄러워서 견딜 수 없게 되었을 즈음 이렇게 하면 되는구나 생각이 났다.


예를 들어, 0부터 5까지의 정수 4개를 이용하여 5를 만든다고 해보자.

그러면 처음에는

1000

0100

0010

0001

로 시작할 수 있다.

이 네 개를 단위벡터 단위행렬... 처럼 하나의 단위로 생각하고 2번째도 구하면 된다.

1000+1000=2000

1000+0100=1100

1000+0010=1010

1000+0001=1001

이런 식으로.

그런데 0100부터는

0100+1000=1100

이므로 중복이 생겨버린다.

따라서 자기 자신과 일치하는 것부터 더해주면 되는 것이다.

이런식으로 다음은 4+3+2+1=10


1차원 배열로 풀려다가 그 전항 정보도 알아야 하고 이 쪽이 직관적이어서 2차원 배열을 택했다...

아무튼 dp[2][1]=4, dp[2][2]=3, dp[2][3]=2, dp[2][4]=1을 저장해준다.

이런 식으로 반복하면 다음의 코드가 나온다.

3번째도 마찬가지로

dp[3][1]=dp[2][1]+dp[2][2]+dp[2][3]+dp[2][4]

dp[3][2]=dp[2][2]+dp[2][3]+dp[2][4]

dp[3][3]=dp[2][3]+dp[2][4]

dp[3][4]=dp[2][4]

이렇게 반복될 수 있는 이유는, n번째의 합은 n-1번째+1번째이기 때문이다.

따라서 1, 2, 3, 4번째를 차례대로 더해주면 답을 구할 수 있는 것이다.





코드

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
26
27
28
29
#include <iostream>
#define MOD 1000000000
using namespace std;
int main() {
    int N, K;
    cin>>N>>K;
    if(K==1) {
        cout<<1<<endl;
        return 0;
    }
    int sum=0, dp[201][201]={0,};
    for(int i=0; i<K; i++) {
        dp[1][i]=1;
    }
    for(int i=2; i<=N; i++) {
        for(int j=0; j<K; j++) {
            for(int k=j; k<K; k++) {
                dp[i][j]+=dp[i-1][k]%MOD;
                dp[i][j]%=MOD;
            }
        }
    }
    for(int i=0; i<K; i++) {
        sum+=dp[N][i];
        sum%=MOD;
    }
    cout<<sum<<endl;
    return 0;
}
cs


'PS' 카테고리의 다른 글

백준 11004번 C++ K번째 수  (0) 2019.06.10
백준 10824번 C++ 네 수  (0) 2019.06.07
백준 9461번 C++ 파도반 수열  (0) 2019.06.01
백준 1912번 C++ 연속합  (0) 2019.05.30
백준 1015번 C++ 수열 정렬  (0) 2019.05.29

댓글