https://www.acmicpc.net/problem/11401
11401번: 이항 계수 3
자연수 \(N\)과 정수 \(K\)가 주어졌을 때 이항 계수 \(\binom{N}{K}\)를 1,000,000,007로 나눈 나머지를 구하는 프로그램을 작성하시오.
www.acmicpc.net
우선, 이 문제와 같이 복잡한 식( N! * [R!(N-R)!] ^ mod-2) % mod )과 같은 경우에는 식을 최소한으로 간결하게 생각할 필
요가 있다.
N! * [R!(N-R)!] ^ mod-2) % mod 은 아래와 같이 변형시킬 수가 있다.
1. N! % mod
2.[ R!(N-R)! ^ mod-2] % mod
3. (1 * 2) % mod(최종식)
-> 문제는 2의 식이였다. 위 식을 필자는 아무 생각 없이 곱의 합동식의 성질을 사용하여 식을 막 늘여 버렸다.
그러다 보니, 내가 뭘 하고 있는지 모르겠는 상황이 발생을 했었다.
되도록 간단하게 생각을 해보자.
R!(N-R)! 을 A라고 치환을 해 보자.
[A^mod-2] % mod
mod - 2 == 2라고 해 보자.
[A^2] % mod == ( A % mod ) ^2 % mod 로 변형이 가능하며, 식의 계산이 훨씬 쉬워 진다.
Q. 아래 코드의 문제점은 무엇인가??
unsigned long long result1 = 1;
for (int x = 1; x <= n;x++) {
result1 *= x;
result1 %= mod;
}
A. result *= x; 에서 오버 플로우가 발생할 가능성이 있다.(실제로, 오버 플로우가 발생하여 게속, 틀렸음)( 재귀 함수를 사용하면, 오버 플로우가 발생하지 않게 짤 수가 있다.)
Solution : 아래의 코드대로 짜면, 반복문이라도 오버 플로우가 발생하지 않는다. ( 아래 코드를 이해하기 위해서는 약간의 증명이 필요하다. 아래에 증명이 있다.)
B=1;
// R! 구하기
for(ll i = 1; i <= R; i++){
B *= i;
B %= MOD;
}
// R!(N-R)! 구하기
for(ll i = 1; i <= N - R; i++){
B *= i;
B %= MOD;
}
예를 들어, 2! % MOD를 구해보자
1 ] i == 1
B = 1
B = 1 % MOD
2] i == 2
B = (1 % MOD) * 2
B = [ (1 % MOD) * 2 ] % MOD
Q. 과연 [ (1 % MOD) * 2 ] % MOD이 2! % MOD와 동치일까???
증명)
(1 % MOD)%MOD * 2 % MOD == (1%MOD) * (2 % MOD) == ( 1 * 2 ) % MOD
결론 : 식을 무조건 원자 레벨까지 아무 생각없이 변형시키지는 말자!!!
참고 사이트https://nicotina04.tistory.com/65
페르마의 소정리를 활용한 알고리즘 문제 풀기
이 게시글에서는 페르마의 소정리를 간략하게 배우고 관련 알고리즘 문제를 푼다. 정수 a와 p가 있고 a가 p의 배수가 아니면서 p가 소수(Prime number)일 때 다음이 성립한다. $a^{p} \equiv a (\mod p)$ 여기
nicotina04.tistory.com
'알고리즘(アルゴリズム) > 알고리즘 이모저모(アルゴリズムの緒論)' 카테고리의 다른 글
행렬의 거듭 제곱( feat. 단위 행렬) (2) | 2023.01.31 |
---|---|
정적 할당 VS 동적 할당 - 메모리 교환 (0) | 2023.01.29 |
pre-condition을 고려하며 function 작성하자!!!! (0) | 2023.01.28 |
합동식(modular)을 왜 쓰는 걸까??? (0) | 2023.01.28 |
재귀함수 -> 반복문 : stack , queue 자료구조를 적극 활용하자!!! (1) | 2023.01.26 |