페르마의 소정리

국동진·2023년 11월 5일
0

Problem Solving

목록 보기
1/1

페르마의 소정리

pp가 소수이면, 모든 정수 aa에 대해 apa  (mod  p)a^p \equiv a \; (mod \; p)이다.
혹은, pp가 소수이고 aapp의 배수가 아니면, ap11  (mod  p)a^{p-1} \equiv 1 \; (mod \; p) 이다.

이를 이용해서 이항계수를 빠르게 구할 수 있습니다.

백준 11401 이항 계수 3

이항 계수 (NK)\binom{N}{K}를 변환하여 페르마의 소정리를 이용할 수 있습니다.

(NK)=N!K!(NK)!=N!(K!(NK)!)1\binom{N}{K} = \frac{N!}{K!(N-K)!} = N!({K!(N-K)!})^{-1}와 같이 변환이 가능하고,
페르마의 소정리를 이용하여
(NK)  %  p=N!(K!(NK)!)p2  %  p\binom{N}{K} \; \% \; p = N!({K!(N-K)!})^{p - 2} \; \% \; p가 성립합니다. (위 문제에서, pp는 1,000,000,007)


코드 (C++)

#include <bits/stdc++.h>

using namespace std;

const int P = 1000000007;

long long getFactorial(long long n)
{
	long long ret = 1;

	for (int i = 1; i <= n; i++) {
		ret = ret * i % P;
	}
	return ret;
}

long long fastMultiply(long long a, long long b)
{
	if (b == 0) return 1;
	if (b == 1) return a % P;

	long long tmp = fastMultiply(a, b / 2);

	if (b % 2 == 0) {
		return tmp * tmp % P;
	} else {
		return tmp * tmp % P * a % P;
	}
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

	long long N, K;
	cin >> N >> K;

	cout << getFactorial(N) * fastMultiply(getFactorial(K) % P * getFactorial(N - K) % P, P - 2) % P << "\n";
	return 0;
}

0개의 댓글