이항계수는 조합론에서 핵심적인 개념으로, 다양한 수학적 문제와 알고리즘에 활용됩니다. 이 글에서는 이항계수의 개념부터 계산 방법, 그리고 프로그래밍에서의 효율적인 구현 방법까지 상세히 알아보겠습니다.
📚 이항계수의 기본 개념
이항계수는 수학적으로 매우 중요한 개념으로, 조합론에서 빈번하게 사용됩니다.
1. 이항계수의 정의
– 이항계수(binomial coefficient)는 이항식을 이항 정리로 전개했을 때 각 항의 계수입니다2.
– 크기가 n인 집합에서 크기가 k인 부분집합을 선택하는 방법의 수를 나타냅니다2.
– 표기법으로는 nCk, C(n,k) 또는 **$\binom{n}{k}$**를 사용합니다.
– 수식으로는 **nCk = n! / (k! × (n-k)!)**로 정의됩니다7.
2. 이항계수의 성질
– nC0 = nCn = 1: n개 중 0개 또는 n개를 모두 선택하는 방법은 각각 1가지뿐입니다7.
– nCk = nC(n-k): 이항계수는 대칭적인 성질을 가집니다7.
– nCk = (n-1)C(k-1) + (n-1)Ck: 이는 파스칼의 법칙으로 알려진 중요한 점화식입니다7.
🔺 파스칼의 삼각형
이항계수를 시각적으로 표현한 파스칼의 삼각형은 수학적 패턴을 이해하는 데 큰 도움이 됩니다.
1. 파스칼 삼각형의 구조
– 파스칼의 삼각형은 이항계수를 삼각형 모양으로 배열한 것입니다3.
– 첫 번째 줄에는 1을 쓰고, 그 다음 줄을 만들 때는 바로 위의 왼쪽 숫자와 오른쪽 숫자를 더합니다3.
– 삼각형의 각 행은 이항계수의 값을 나타내며, n번째 행의 k번째 값은 nCk입니다3.
2. 파스칼 삼각형의 성질
– 각 행의 첫 번째와 마지막 숫자는 항상 1입니다3.
– 삼각형의 각 수는 바로 위의 두 수의 합과 같습니다7.
– 이 성질은 이항계수의 점화식 nCk = (n-1)C(k-1) + (n-1)Ck와 정확히 일치합니다7.
💻 이항계수의 프로그래밍적 구현
이항계수 계산은 다양한 알고리즘 문제에서 자주 등장하며, 효율적인 구현이 중요합니다.
1. 단순 재귀 방식
– 가장 직관적인 방법으로, 점화식을 그대로 구현합니다7.
– 코드는 간단하지만, 중복 계산으로 인해 O(2^n)의 시간 복잡도를 가집니다7.
– 큰 입력값에 대해서는 제한 시간 내에 문제를 해결할 수 없습니다7.
def bino(n, k):
if k == 0 or n == k:
return 1
return bino(n-1, k-1) + bino(n-1, k)
2. 메모이제이션을 활용한 재귀 (Top-down DP)
– 한 번 계산한 부분 문제의 결과를 저장하여 중복 계산을 방지합니다5.
– 필요한 부분만 계산하여 효율적입니다5.
– 재귀 함수 호출 오버헤드가 있지만, 필요한 값만 계산하므로 특정 상황에서 유리합니다5.
def bino(n, k):
if cache[n][k] != 0:
return cache[n][k]
if k == 0 or n == k:
return 1
cache[n][k] = (bino(n-1, k-1) + bino(n-1, k)) % MOD
return cache[n][k]
3. 반복문을 이용한 DP (Bottom-up DP)
– 작은 부분 문제부터 차례로 해결하며 테이블을 채워나갑니다5.
– 함수 호출 오버헤드가 없어 일반적으로 더 빠릅니다5.
– 모든 부분 문제를 해결해야 할 때 유리합니다5.
for i in range(1001):
cache[i][0] = 1
cache[i][i] = 1
for j in range(1, i):
cache[i][j] = (cache[i-1][j-1] + cache[i-1][j]) % MOD
https://www.acmicpc.net/problem/11051
메모이제이션이나 반복문으로 해결 가능
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7) # 재귀 깊이 제한 늘리기
# 일단 단순하게 재귀로 구현
# 1000 500 넣으면 시간초과
MOD = 10007
N,K = map(int, input().split())
def bino(n,k):
if k == 0 or n == k:
return 1
return bino(n-1,k-1) + bino(n-1,k)
print(bino(N,K))
# 메모이제이션을 이용한 재귀
MOD = 10007
N,K = map(int, input().split())
cache = [[0] * 1001 for _ in range(1001)]
def bino(n,k):
if cache[n][k] != 0:
return cache[n][k]
if k == 0 or n == k:
return 1
cache[n][k] = (bino(n-1,k-1) + bino(n-1,k)) % MOD
return cache[n][k]
print(bino(N,K))
# 반복문을 이용한 DP
MOD = 10007
N,K = map(int, input().split())
cache = [[0] * 1001 for _ in range(1001)]
for i in range(1001):
cache[i][0] = 1
cache[i][i] = 1
for j in range(1, i):
cache[i][j] = cache[i-1][j-1] + cache[i-1][j]
cache[i][j] %= MOD
print(cache[N][K])
🔄 재귀 깊이 제한과 대규모 계산
재귀 함수를 사용할 때는 몇 가지 제약 사항에 주의해야 합니다.
1. 파이썬의 재귀 깊이 제한
– 파이썬의 기본 재귀 깊이 제한은 1000입니다1113.
– 이를 초과하면 RecursionError가 발생합니다14.
– sys.setrecursionlimit() 함수를 사용하여 제한을 늘릴 수 있습니다1113.
import sys
sys.setrecursionlimit(10**6) # 재귀 깊이를 백만으로 설정
2. 대규모 이항계수 계산과 모듈러 연산
– 이항계수 값은 n과 k가 커질수록 매우 빠르게 증가합니다4.
– 오버플로우를 방지하기 위해 모듈러 연산을 사용합니다4.
– 모듈러 연산의 성질: (a + b) % n = ((a % n) + (b % n)) % n4.
– 이를 활용하여 큰 이항계수 값도 효율적으로 계산할 수 있습니다4.
🔍 Top-down DP와 Bottom-up DP 비교
두 방식은 각각 장단점이 있어 상황에 따라 적절한 방법을 선택해야 합니다.
1. Top-down DP (메모이제이션)
– 장점: 직관적인 구현, 필요한 부분만 계산, 코드 가독성이 좋음5.
– 단점: 재귀 함수 호출 오버헤드, 스택 메모리 사용, 재귀 깊이 제한5.
– 적합한 경우: 모든 부분 문제를 계산할 필요가 없을 때5.
2. Bottom-up DP (테이블레이션)
– 장점: 재귀 없이 반복문만 사용하여 메모리와 시간 효율적5.
– 단점: DP 테이블을 채우는 순서를 정확히 파악해야 함5.
– 적합한 경우: 모든 부분 문제를 계산해야 할 때, 메모리 효율성이 중요할 때5.
📐 이항계수의 응용
이항계수는 다양한 분야에서 응용됩니다.
1. 조합론적 응용
– 조합의 수 계산: n개 중 k개를 선택하는 방법의 수2.
– 카탈랑 수 계산: 다양한 조합론적 문제의 해법2.
– 중복집합 선택: n개 중 k개를 중복 허용하여 선택하는 방법의 수2.
2. 대수학과 통계학
– 이항식 전개: (x + y)^n의 전개2.
– 이항분포: 확률 분포 정의2.
– 정수론: 베르트랑의 공준 증명, 아페리 상수 관련 급수2.
📝 결론
이항계수는 수학과 컴퓨터 과학에서 중요한 개념으로, 효율적인 계산 방법을 이해하는 것이 알고리즘 문제 해결에 큰 도움이 됩니다.
– 이항계수는 조합론, 대수학, 통계학 등 다양한 분야에서 활용됩니다2.
– 계산 방법으로는 단순 재귀, Top-down DP, Bottom-up DP 등이 있으며, 각각 장단점이 있습니다57.
– 파이썬에서 재귀를 사용할 때는 재귀 깊이 제한에 주의해야 합니다111314.
– 대규모 계산 시 모듈러 연산을 활용하여 오버플로우를 방지할 수 있습니다4.
이항계수의 개념과 계산 방법을 제대로 이해한다면, 다양한 알고리즘 문제를 효율적으로 해결할 수 있을 것입니다.
Citations:
- https://www.acmicpc.net/problem/11051
- https://ko.wikipedia.org/wiki/%EC%9D%B4%ED%95%AD_%EA%B3%84%EC%88%98
- https://ko.wikipedia.org/wiki/%ED%8C%8C%EC%8A%A4%EC%B9%BC%EC%9D%98_%EC%82%BC%EA%B0%81%ED%98%95
- https://suri78.tistory.com/41
- https://devruby7777.tistory.com/entry/Top-down-DP%EC%99%80-Bottom-up-DP%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90%EA%B3%BC-%EC%9E%A5%EB%8B%A8%EC%A0%90-%EC%93%B0%EB%8A%94-%EA%B2%BD%EC%9A%B0
- https://jlog1016.tistory.com/23
- https://rh-tn.tistory.com/32
- https://optboy.github.io/markdown/2020/03/01/markdown.html
- https://blog.naver.com/surfer_of_life/222004981175
- https://velog.io/@newdana01/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%9D%B4%ED%95%AD%EA%B3%84%EC%88%98%EB%9E%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B5%AC%ED%98%84
- https://makasti.tistory.com/108
- https://blog.naver.com/prayer2k/222632101723
- https://ye5ni.tistory.com/178
- https://dinae.tistory.com/73
- https://shoark7.github.io/programming/algorithm/3-ways-to-get-binomial-coefficients
- https://noanomal.tistory.com/509
- https://yabmoons.tistory.com/539
- https://www.youtube.com/watch?v=M6tVz2g6Q3s
- https://blog.naver.com/vollollov/220947452823
- https://ldgeao99.tistory.com/369
- https://blog.naver.com/jinhan814/222603789811
- https://growth-coder.tistory.com/90
- https://blog.naver.com/junhyuk7272/222053814549
- https://indv-wrappedmath.tistory.com/entry/%ED%8C%8C%EC%8A%A4%EC%B9%BC%EC%9D%98-%EC%82%BC%EA%B0%81%ED%98%95
- https://velog.io/@e414/%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A1%B0%ED%95%A9-%EC%9D%B4%ED%95%AD%EA%B3%84%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B02
- https://velog.io/@kimdukbae/%EB%8B%A4%EC%9D%B4%EB%82%98%EB%AF%B9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-Dynamic-Programming
- https://www.acmicpc.net/problem/11051
- https://kbhetrr.dev/blog/binomial-coefficient/
- https://hgk5722.tistory.com/93
- https://seungjuitmemo.tistory.com/85
- https://mindorizip.tistory.com/80
- https://www.youtube.com/watch?v=Dcd9kHu6c54
- https://velog.io/@chulxmin/Python-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%B5%9C%EB%8C%80-%EC%9E%AC%EA%B7%80-%EC%A0%9C%ED%95%9C-%ED%92%80%EA%B8%B0
- https://velog.io/@imdemo/Tech-Markdown%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4-%EC%A0%95%EB%A6%AC
- https://brunch.co.kr/@donland/41
- https://dykm.tistory.com/72
- https://haamjamie.tistory.com/6
- https://velog.io/@if-else/%EC%9E%90%EC%A3%BC-%EC%93%B0%EC%9D%B4%EB%8A%94-%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4-%EB%AC%B8%EB%B2%95%EB%93%A4-with-%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8
- https://brunch.co.kr/@or24/35