Post

[BaekJoon] #11051 - 이항 계수 2 [Java][C++]

[BaekJoon] #11051 - 이항 계수 2 [Java][C++]

문제 링크


1. 아이디어

BaekJoon 11050번 - 이항 계수 1 문제에서 $N$과 $K$의 범위가 더 커졌고, 이항 계수를 $10{,}007$로 나눈 나머지를 구해야 하는 문제다. 이전 문제의 재귀 풀이는 같은 부분문제를 반복해서 호출하므로 $N$이 커지면 연산량이 지수적으로 늘어난다. 따라서 다이나믹 프로그래밍을 활용해 각 이항 계수를 한 번씩만 구해야 한다.

파스칼의 삼각형을 2차원 dp 배열로 구현하면 되며 dp[i][j]를 $i$행 $j$열의 이항 계수라 했을 때, dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] 점화식으로 이항 계수를 구할 수 있다.

모듈러 연산은 덧셈에 대해 분배가 가능하므로 이항 계수를 구할 때마다 나머지만 취했다.


2. 복잡도

접근시간공간
풀이$O(N \times K)$$O(N \times K)$

($N$ = 입력값 n, $K$ = 입력값 k. C++는 입력 크기 최대치로 잡은 정적 배열이라 공간 $O(N^2)$)


3. 코드

풀이 [Java][C++]

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
import java.io.*;
import java.util.*;

public class Main {

    static final int MOD = 10007;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int n = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());

        int[][] dp = new int[1 + n][1 + k];
        for (int i = 0; i <= n; i++) {
            dp[i][0] = 1;

            for (int j = 1; j <= Math.min(i, k); j++) {
                dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % MOD;
            }
        }

        System.out.println(dp[n][k]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <bits/stdc++.h>
using namespace std;

const int MOD = 10007;
int dp[1 + 1000][1 + 1000];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, k;
    cin >> n >> k;

    for (int i = 0; i <= n; i++) {
        dp[i][0] = 1;

        for (int j = 1; j <= min(i, k); j++) {
            dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % MOD;
        }
    }

    cout << dp[n][k];
}

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