[백준] 11493번: 이항 계수 5

2019. 8. 2. 16:11알고리즘

문제

자연수 N과 정수 K가 주어졌을 때 이항 계수 (NK) M으로 나눈 나머지를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 NK M이 주어진다. (1 ≤ N ≤ 4×10^6, 0 ≤ K  N, 2 ≤ M ≤ 4×10^6)

출력

 (NK) M으로 나눈 나머지를 출력한다.

 

 

이항 계수의 나머지를 구하는 문제인데, N과 K, M이 모두 크기가 큰 수라 이항 계수를 직접 구해서 계산하는 것으로는 문제를 해결할 수 없습니다. 문제를 해결하기 위해서는, 이항 계수의 성질과 나머지의 성질을 이용해서 문제를 풀어야 합니다. 이항 계수는 N! / (K! * (N - K)!) 라는 것과, 나머지 연산이 곱셈에 대해서는 (A * B) % M = ((A % M) * (A % M)) % M 이라는 것을 알 수 있기 때문에, 이항 계수를 소인수분해해서 안에 있는 소수의 갯수를 세어줍니다. 소수의 갯수만큼 리턴될 변수에 해당 소수를 곱하고, 나머지 연산을 수행해줍니다.

 

#include <iostream>
typedef long long ll;
using namespace std;

bool sieve[4000001];
int numberOfPrime[4000001];

void eratosthenes(int N) {
    for (int i = 2; i * i <= N; i++) {
        if (!sieve[i]) {
            for (int j = i + i; j <= N; j += i) {
                sieve[j] = true;
            }
        }
    }
}

void calculatePrime(int N, int K) {
    for (int i = 2; i <= N; i++) {
        if (!sieve[i]) {
            for (ll factor = i; factor <= N; factor *= i) {
                numberOfPrime[i] += (N / factor) - (K / factor) - ((N - K) / factor);
            }
        }
    }
}

int main() {
    int N, M, K;
    cin >> N >> K >> M;
    eratosthenes(N);
    calculatePrime(N, K);

    ll ans = 1;
    for (int i = 2; i <= N; i++) {
        for (int j = 0; j < numberOfPrime[i]; j++) {
            ans *= i;
            ans %= M;
        }
    }
    cout << ans << '\n';

    return 0;
}

'알고리즘' 카테고리의 다른 글

[LeetCode] Binary Tree Inorder Traversal  (0) 2019.12.21
[프로그래머스] 단어 변환  (0) 2019.10.30
[백준] 10830번: 행렬 제곱  (0) 2019.07.26
[백준] 1016번: 제곱 ㄴㄴ 수  (0) 2019.07.26
[백준] 1629번: 곱셈  (0) 2019.07.26