조합론 (Combinatorics)
정의
조합론 (Combinatorics) 은 유한 집합의 원소를 세는 수학 분야. PS 에서는 주로 순열 (Permutation), 조합 (Combination), 이항계수 (Binomial Coefficient) 계산과 mod 연산을 다룬다.
핵심 연산:
- nPr (순열): n 개 중 r 개를 순서를 고려해 뽑기 =
n! / (n-r)! - nCr (조합): n 개 중 r 개를 순서 무관 뽑기 =
n! / (r! · (n-r)!) - 이항계수:
C(n, r)= nCr, Pascal 의 삼각형C(n, r) = C(n-1, r-1) + C(n-1, r)
17세기 Blaise Pascal, Pierre de Fermat 등이 확률론과 함께 발전. PS 에서는 DP, mod 1e9+7, Lucas 정리, Catalan 수 등으로 확장.
문제 상황과 동기
경우의 수 세기:
- “N 명 중 K 명을 뽑는 방법?” → nCr
- “길이 N 순열의 개수?” → N!
- “중복 조합?” → (n+r-1)Cr
naive 계산의 한계:
nCr = n! / (r! · (n-r)!)직접 계산: N ≥ 21 이면 팩토리얼 오버플로우.- mod p 연산:
(a / b) mod p는 정의 안 됨 → 역원 필요. - Q 번 쿼리: 매번 팩토리얼 계산하면 O(N · Q) → O(N + Q) 로.
핵심 통찰:
- 전처리 + 역원:
fact[n],inv_fact[n]을 O(N) 에 미리 계산 → nCr mod p O(1) 쿼리. - Pascal 의 삼각형 DP:
C[n][r] = C[n-1][r-1] + C[n-1][r]→ O(N²) 전처리, mod 연산 깔끔. - Lucas 정리: mod p (p 소수, 작은 p) 일 때 O(p² log_p N) 계산.
시각화
핵심 아이디어
1. 순열 (nPr)
n 개 중 r 개를 순서를 고려해 뽑기.
nPr = n · (n-1) · ... · (n-r+1) = n! / (n-r)!
2. 조합 (nCr)
n 개 중 r 개를 순서 무관 뽑기. 순열에서 r! 로 나눔 (중복 제거).
nCr = n! / (r! · (n-r)!)
대칭성: C(n, r) = C(n, n-r).
3. Pascal 의 삼각형
C(n, r) = C(n-1, r-1) + C(n-1, r)
base: C(n, 0) = C(n, n) = 1.
invariant: 이항정리 (1 + x)^n = Σ C(n, r) x^r.
4. mod p 계산 (p 소수)
Fermat 의 소정리 또는 확장 유클리드로 역원 구하기.
nCr_mod_p = fact[n] * inv_fact[r] % p * inv_fact[n-r] % p
알고리즘
팩토리얼 + 역원 전처리 (mod p)
precompute(N, p):
fact[0] = 1
for i = 1..N:
fact[i] = fact[i-1] * i % p
inv_fact[N] = inv(fact[N], p) # Fermat or exgcd
for i = N-1..0:
inv_fact[i] = inv_fact[i+1] * (i+1) % p
nCr_mod(n, r, p):
if r < 0 or r > n: return 0
return fact[n] * inv_fact[r] % p * inv_fact[n-r] % p
Pascal 의 삼각형 DP
build_pascal(N):
C[0][0] = 1
for n = 1..N:
C[n][0] = 1
for r = 1..n:
C[n][r] = C[n-1][r-1] + C[n-1][r]
구현
// nCr mod p (팩토리얼 + 역원 전처리)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
const long long MOD = 1000000007;
long long fact[MAXN], inv_fact[MAXN];
long long pow_mod(long long a, long long n, long long m) {
long long r = 1;
a %= m;
while (n > 0) {
if (n & 1) r = r * a % m;
a = a * a % m;
n >>= 1;
}
return r;
}
void precompute(int n, long long p) {
fact[0] = 1;
for (int i = 1; i <= n; i++)
fact[i] = fact[i-1] * i % p;
inv_fact[n] = pow_mod(fact[n], p - 2, p);
for (int i = n - 1; i >= 0; i--)
inv_fact[i] = inv_fact[i+1] * (i+1) % p;
}
long long nCr(int n, int r) {
if (r < 0 || r > n) return 0;
return fact[n] * inv_fact[r] % MOD * inv_fact[n-r] % MOD;
}
int main() {
int n, r;
cin >> n >> r;
precompute(n, MOD);
cout << nCr(n, r) << "\n";
return 0;
}5 210복잡도
| 방법 | 전처리 | 쿼리 | 공간 | 조건 |
|---|---|---|---|---|
| 팩토리얼 + 역원 | O(N + log p) | O(1) | O(N) | mod p (p 소수) |
| Pascal DP | O(N²) | O(1) | O(N²) | 작은 N ≤ 1000 |
| Lucas 정리 | O(p² + log_p N) | O(log_p N) | O(p²) | p 작은 소수 |
| 직접 계산 | - | O(r) | O(1) | mod 없고 작은 r |
응용
1. 이항정리
(x + y)^n = Σ (r=0 to n) C(n, r) x^(n-r) y^r
2. 중복 조합
n 가지에서 r 개를 중복 허용 뽑기 (순서 무관):
H(n, r) = C(n + r - 1, r)
3. Catalan 수
Cat(n) = C(2n, n) / (n + 1) = C(2n, n) - C(2n, n+1)
올바른 괄호 문자열, BST 개수, 산 모양 경로 등.
4. 포함-배제 원리
|A ∪ B| = |A| + |B| - |A ∩ B|
일반화: |A₁ ∪ ... ∪ Aₙ| = Σ|Aᵢ| - Σ|Aᵢ ∩ Aⱼ| + ...
5. Stirling 수
- 제1종: 순열을 cycle 로 분해
- 제2종: n 개 원소를 k 개 비어있지 않은 부분집합으로
함정
1. 팩토리얼 오버플로우
n! 은 n ≥ 21 이면 long long 넘음. mod 연산 또는 큰 수 라이브러리.
2. 역원 존재 조건
mod p 가 소수가 아니면 Fermat 불가. 확장 유클리드 또는 Lucas (p 소수 분해).
3. nCr = 0 케이스
r > n 또는 r < 0 일 때 0. 경계 체크 누락하면 WA.
4. mod 연산 순서
(a / b) % p (X) → a * inv(b, p) % p (O).
5. 중복 조합 실수
“중복 허용 조합” 은 C(n, r) 이 아니라 C(n+r-1, r).
변형
| 변형 | 설명 |
|---|---|
| Lucas 정리 | nCr mod p (p 소수) 를 O(log_p N) |
| Catalan 수 | Cat(n) = C(2n, n) / (n+1), 괄호 문자열 등 |
| Stirling 수 | 순열 cycle 분해, 집합 분할 |
| Derangement | 고정점 없는 순열, D(n) = n! Σ (-1)^k / k! |
| Binomial inversion | Möbius 변환, 포함-배제 |
BOJ 연습 문제
| 번호 | 제목 | 정답률 | 링크 |
|---|---|---|---|
| BOJ 11050 | 이항 계수 1 | - | kokoa-lab |
| BOJ 11051 | 이항 계수 2 | - | kokoa-lab |
| BOJ 11401 | 이항 계수 3 | - | kokoa-lab |
| BOJ 11402 | 이항 계수 4 (Lucas) | - | kokoa-lab |
| BOJ 13977 | 이항 계수와 쿼리 | - | kokoa-lab |
참고
이 글의 용어 (4개)
- 뤼카 정리 (Lucas Theorem)algorithm
- 정의 뤼카 정리 (Lucas Theorem) 는 소수 p 에 대해 큰 n, r 의 이항 계수 nCr 을 p 로 나눈 나머지를 O(logp N) 에 구하는 방법. n, r 을 p …
- 모듈러 역원 (Modular Multiplicative Inverse)algorithm
- 정의 정수 a 의 모듈러 역원 (modular multiplicative inverse) 은 을 만족하는 정수 x. 기호로 또는 . 존재 조건: gcd(a, m) = 1 일 때만…
- Catalan Number: C_nalgorithm
- 정의 Catalan number: $$ Cn = \frac{1}{n+1} \binom{2n}{n} = \frac{(2n)!}{(n+1)! \, n!} $$ C0 = 1, C1 =…
- Pascal Triangle: 이항계수algorithm
- 정의 Pascal Triangle 은 각 원소가 위 두 원소의 합인 삼각형. 행 n, 열 k 의 원소가 이항계수 $\binom{n}{k}$. 계산 O(N²) 공간/시간. 성질 -…
이 개념을 다룬 위키 페이지 (11)
- wiki수학 (Mathematics)
- wiki번사이드 보조정리 (Burnside's Lemma)
- wiki베이즈 정리 (Bayes Theorem)
- wikiCatalan Number: C_n
- wiki포함-배제 원리 (Inclusion-Exclusion Principle)
- wikiInclusion and Exclusion: 포함배제 원리
- wikiLinearity of Expectation (기댓값의 선형성)
- wiki모듈러 역원 (Modular Multiplicative Inverse)
- wikiPascal Triangle: 이항계수
- wikiPigeonhole Principle (비둘기집 원리)
- wiki확률 (Probability)
💬 댓글