일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 13164
- 맵
- 플로이드-워셜
- 정렬
- 정수론
- 누적 합
- 투 포인터
- BFS
- 구현
- 문자열
- SSAFY
- 수학
- boj
- 애드 혹
- 트리
- 세그먼트 트리
- Python
- 2357
- 이분 탐색
- 그래프
- 해시 테이블
- 에라토스테네스의 체
- DP
- 그리디
- JavaScript
- 모던 JavaScript 튜토리얼
- DFS
- 슬라이딩 윈도우
- 브루트포스
- 싸피
- Today
- Total
흙금이네 블로그
[BOJ] 11401 - 이항 계수 3 (Python) 본문
아이디어
모듈러 연산의 분배법칙과 페르마의 소정리로 계산식을 바꾼 후, 이분 탐색을 이용해 계산한다.
풀이
\(\binom{N}{K}\)는 \(\frac{N!}{K!(N-K)!}\)이고, \(\frac{N!}{K!(N-K)!}=\frac{N\cdot(N-1)\cdot\cdots\cdot(N-K+1)}{K!}\)이다.
결과값은 1,000,000,007로 나눈 나머지이므로 계산 과정에서 모듈러 연산의 곱셈에 대한 분배법칙을 이용할 수 있다.
\((a\bmod p)\cdot(b\bmod p)=ab\bmod p\)
따라서 계산 과정에서 발생하는 중간값들을 모두 1,000,000,007로 나눈 나머지로 두고 계산할 수 있다.
모듈러 연산의 곱셈에 대한 분배법칙으로 분모와 분자를 각각 1,000,000,007로 나눈 나머지로 계산하여 둔다.
그러나 모듈러 연산에서 나눗셈에 대한 분배법칙은 성립하지 않으므로,
분자를 분모로 나누는 대신 분자에 분모의 곱셈의 역원을 곱하여 계산하도록 한다.
페르마의 소정리에 따라 \(p\)가 소수이고 \(a\)가 \(p\)의 배수가 아니면 \(a^{p-1}\equiv 1\)이 성립하는데,
\(p\)는 1,000,000,007로 소수이고 분모 \(a\)는 1,000,000,007로 나눈 나머지이므로 항상 이 조건을 만족한다.
\(a^{p-1}\equiv 1\)에서 양변을 \(a\)로 나누면 \(a\cdot a^{p-2}\equiv a^{-1}\)가 되므로 \(a\)의 역원은 \(a^{p-2}\)이 된다.
분모의 역원을 구할 때에는 이분 탐색을 이용해 빠르게 계산하며 마찬가지로 모듈러 연산의 분배법칙을 이용한다.
def solution():
def power(b, pw):
if pw == 1:
return b
if pw%2:
return ((power(b, pw//2)**2)*b)%p
return (power(b, pw//2)**2)%p
N, K = map(int, input().split())
p = 1000000007
if N-K < K:
K = N-K
num = den = 1
for i in range(K):
num = num*(N-i)%p
den = den*(K-i)%p
print(num*power(den, p-2)%p)
solution()
파이썬 내장 함수 pow()를 사용하여 거듭제곱을 계산할 수도 있다.
print(num*pow(den, p-2, p)%p)
'알고리즘' 카테고리의 다른 글
[BOJ] 9376 - 탈옥 (Python) (0) | 2023.04.11 |
---|---|
[BOJ] 2933 - 미네랄 (Python) (0) | 2023.04.11 |
[BOJ] 3197 - 백조의 호수 (Python) (0) | 2023.04.10 |
[BOJ] 17387 - 선분 교차 2 (Python) (0) | 2023.04.08 |
[BOJ] 2186 - 문자판 (Python) (0) | 2023.04.07 |