본문 바로가기

알고리즘 스터디

[Python] BOJ 11051 이항 계수2

728x90

출처 : 백준

이 문제를 처음엔 자바로 풀려고 했지만 12! 이 넘어가면 int 형을 초과하고 20! 을 넘어가면 long 형을 초과하여 엉뚱한 숫자가 튀어나온다. 이를 해결하기 위해선 모듈러 증명과 페르마의 소정리에 대한 수학적 지식이 있어야 알고리즘으로 접근할 수 있다. 

 

정석으로 풀기 위해선 이분 블로그를 참고하면 좋을 것 같다.

https://st-lab.tistory.com/162

 

[백준] 11051번 : 이항 계수 2 - JAVA [자바]

www.acmicpc.net/problem/11051 11051번: 이항 계수 2 첫째 줄에 \(N\)과 \(K\)가 주어진다. (1 ≤ \(N\) ≤ 1,000, 0 ≤ \(K\) ≤ \(N\)) www.acmicpc.net 문제 이전의 이항 계수 1 문제와 같은 문제다. 다만 출..

st-lab.tistory.com

 

필자의 포스팅에선 자바가 아닌 파이썬으로 이를 해결한 과정을 포스팅 하고자 한다.

 

이에 앞서 자바나 C++ 과 같이 변수의 크기를 지정해주거나 데이터 타입을 명시해줘야 하는 언어와는 달리 파이썬 3에서는 long 타입이 없어지고 int 타입만 남았는데, 이 int가 arbitrary precision을 지원하여 데이터 타입의 오버플로우가 발생하지 않는다. 

arbitrary precision
In computer science, arbitrary-precision arithmetic, also called bignum arithmetic, multiple precision arithmetic, or sometimes infinite-precision arithmetic, indicates that calculations are performed on numbers whose digits of precision are limited only by the available memory of the host system
-Wikepedia

arbitrary precision은 쉽게 말해 메모리를 미리 정해놓지 않고 컴퓨터의 사용 가능한 메모리를 필요할 때 가져다 쓰는 것이다. 그러니까 수가 엄청나게 커져도 컴퓨터의 메모리가 허락하는 한 오버플로우가 발생하지 않는다.

 

파이썬 코드는 다음과 같다.

a,b = map(int, input().split())

def factorial(n,m):
    sum = n
    for i in range(m-1):
        n-=1
        sum *= n
    return sum

def r_factorial(n):
    if n==0:
        return 1
    sum = 1
    for i in range(n,1,-1):
        sum *= i
    return sum

print(int((factorial(a,b)//r_factorial(b)))%10007)

우리가 흔히 이항 계수를 계산할 때 예를 들어 5C2라고 한다면, 분자는 5 * 4, 분모는 2! 이 된다. 분자는 5에서 시작해 2번의 팩토리얼 연산을 진행한다. 

 

aCb라고 하면, a*(a-1)*(a-2)*...(a-(a-b)+1) / b! 인 것을 그대로 구현한 코드이다. 단, 분자와 분모를 나누어 줄 때 int/int 는 float 형이 되기 때문에 부동소수점 에러가 발생할 수 있어서 int // int로 해주어야만 정상적인 값이 나온다.

'알고리즘 스터디' 카테고리의 다른 글

[JAVA] BOJ 9375 패션왕 김해빈  (0) 2021.07.21
[Python] BOJ 1010 다리놓기  (0) 2021.07.20
[JAVA + Python] BOJ 2981 검문  (0) 2021.07.19
[JAVA + Python] BOJ 1934 최소공배수  (0) 2021.07.17
[JAVA] BOJ 13305 주유소  (0) 2021.07.15