[백준] 11401번 - 이항 계수 3 [Java]
[백준] 11401번 - 이항 계수 3 [Java]
문제 풀이
자연수 $N$ 과 정수 $K$ 에 대한 이항 계수를 1,000,000,007로 나눈 나머지를 구해야 하는 문제다. 단순한 다이나믹 프로그래밍으로는 해결할 수 없는데 페르마의 소정리와 분할 정복을 이용한 거듭 제곱을 적용하면 해결할 수 있다.
이항 계수의 경우 분모를 모듈러 곱셈 역원으로 바꾸면 아래와 같이 된다.(p = 1,000,000,007 이고 p는 소수이며 k!, (n-k)!과 서로소라 모듈러 곱셈 역원이 존재하는 상황)
이제 팩토리얼과 역팩토리얼 배열을 만들면 저 식의 값을 계산할 수 있는 데, 팩토리얼 배열의 경우 점화식으로 초기화하되 모듈러를 적용해서 오버플로우를 방지했다. 역팩토리얼 배열의 경우 아래 식으로 계산할 수 있다.
\[k! = k\cdot (k-1)!\] \[(k-1)!^{-1} \equiv k \cdot (k!)^{-1} \pmod{p}\]초항의 경우 페르마의 소정리를 활용하면 아래와 같이 구할 수 있다.
\[k!^{-1} \equiv (k!)^{p-2} \pmod{p}\]여기서 p-2 = 1,000,000,005 이므로 해당 거듭 제곱 연산을 분할 정복을 이용한 거듭 제곱으로 구하면 된다.
코드
1. 풀이 [Java]
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.*;
import java.util.*;
public class Main {
private static final int MOD = 1_000_000_007;
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());
long[] fact = initFact(N); // 팩토리얼 배열
long[] invFact = initInvFact(N, fact[N]); // 역팩토리얼 배열(모듈러 역원)
System.out.println(fact[N] * invFact[K] % MOD * invFact[N - K] % MOD);
}
private static long[] initFact(int N) {
long[] fact = new long[1 + N];
fact[0] = 1;
for (int i = 1; i <= N; i++) {
fact[i] = fact[i - 1] * i % MOD;
}
return fact;
}
private static long[] initInvFact(int N, long a) {
long[] invFact = new long[1 + N];
invFact[N] = modPow(a, MOD - 2); // 역팩토리얼의 초항(페르마의 소정리 활용)
for (int i = N - 1; i >= 0; i--) {
invFact[i] = invFact[i + 1] * (i + 1) % MOD;
}
return invFact;
}
// a^b % mod를 구하는 메서드(분할 정복을 이용한 거듭제곱)
private static long modPow(long a, int b) {
if (b == 0) return 1;
long half = modPow(a, b / 2);
if (b % 2 == 0) {
return half * half % MOD;
} else {
return half * half % MOD * a % MOD; // half * half * a가 long형 범위를 넘어갈 수 있어서 미리 mod 수행
}
}
}
풀이 정보
1. 풀이 [Java]
- 19 min
This post is licensed under CC BY 4.0 by the author.


