조합(Combination)이란?
조합은 서로 다른 n개의 원소에서 순서를 생각하지 않고 k개를 뽑는 경우의 수를 의미합니다. 예를 들어, 3명의 학생 {A, B, C} 중에서 2명을 뽑는 경우, {A, B}, {A, C}, {B, C}의 3가지가 있으며, {A, B}와 {B, A}는 같은 경우로 취급합니다.
조합은 이항 계수(Binomial Coefficient)와도 밀접한 관련이 있으며, nCk 또는 C(n, k)로 표기합니다.
조합의 특징
- 순서 무시: 원소를 뽑는 순서는 결과에 영향을 주지 않음
- 핵심 공식:
nCk = n! / (k! * (n-k)!)- 응용 분야: 확률, 통계, 경우의 수를 다루는 다양한 문제의 기반이 됨
조합을 구하는 핵심 이론
조합을 계산하는 가장 기본적인 방법은 수학 공식을 직접 이용하는 것입니다.
1. 팩토리얼(Factorial) 기반 공식
가장 널리 알려진 공식입니다.
nCk = n! / (k! * (n-k)!)
하지만 n이 조금만 커져도 n!의 값은 매우 커지기 때문에, 컴퓨터의 자료형 범위를 초과할 수 있어 직접적인 구현이 어려울 수 있습니다.
2. 순열(Permutation) 기반 공식
팩토리얼의 약분 성질을 이용한 공식으로, 제공된 코드에서 사용한 방식입니다.
nCk = nPk / k!
nCk = (n * (n-1) * ... * (n-k+1)) / (k * (k-1) * ... * 1)
이 방식은 분자와 분모를 각각 계산한 후 나누기 때문에, 중간 계산 과정에서 발생하는 오버플로우를 어느 정도 방지할 수 있습니다.
참고: 파스칼의 삼각형
점화식을 이용하는 방법도 있습니다. nCk = (n-1)C(k-1) + (n-1)Ck. 이 방법은 동적 프로그래밍(DP)으로 구현하며, 모듈러 연산이 포함된 조합 문제에서 매우 유용하게 사용됩니다.
예제: 백준 11051번 “이항 계수 2”
문제 설명
- 자연수
N과 정수K가 주어졌을 때, 이항 계수nCk를 10,007로 나눈 나머지를 출력하라. 1 ≤ N ≤ 1,000,0 ≤ K ≤ N
코드 구현
import sys
input = sys.stdin.readline
N, K = map(int, input().split())
# 분자(Numerator) 계산: n * (n-1) * ... * (n-k+1)
result = 1
for i in range(K):
result *= N
N -= 1
# 분모(Denominator) 계산: k!
divisor = 1
for i in range(2, K + 1):
divisor *= i
# (분자 / 분모) % 10007
print((result // divisor) % 10007)
코드 분석
- 분자 계산 (순열 nPk 부분)
result = 1
for i in range(K):
result *= N
N -= 1
→ 조합 공식 nPk / k!에서 분자에 해당하는 nPk 즉, n * (n-1) * … * (n-k+1)을 계산하는 부분입니다. for 루프가 K번 반복되면서 result에 N을 곱하고, N을 1씩 감소시킵니다. 첫 번째 반복: result = N 두 번째 반복: result = N * (N-1) … K 번째 반복: result = N * (N-1) * … * (N-K+1)
- 분모 계산 (k! 부분)
divisor = 1
for i in range(2, K + 1):
divisor *= i
→ 조합 공식에서 분모에 해당하는 k! (k 팩토리얼)을 계산합니다. divisor에 2부터 K까지의 모든 수를 차례로 곱하여 k!를 만듭니다.
- 최종 계산 및 나머지 연산
print((result // divisor) % 10007)
→ result (분자)를 divisor (분모)로 나눈 후, 그 결과를 10,007로 나눈 나머지를 출력합니다.
정리
| 항목 | 설명 |
|---|---|
| 알고리즘 유형 | 조합론 (Combinatorics), 이항 계수 |
| 주요 조건 | nCk = (nPk) / k! 공식을 이용한 직접 계산 |
| 핵심 자료구조 | 기본 변수를 이용한 누적 곱셈 |
| 시간 복잡도 | O(K) - 분자, 분모 계산에 각각 K번의 반복 필요 |
| 응용 예시 | 경우의 수 계산, 확률 문제, 파스칼의 삼각형 등 |