[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.