반응형

https://www.acmicpc.net/problem/11402

 

11402번: 이항 계수 4

첫째 줄에 \(N\), \(K\)와 \(M\)이 주어진다. (1 ≤ \(N\) ≤ 1018, 0 ≤ \(K\) ≤ \(N\), 2 ≤ \(M\) ≤ 2,000, M은 소수)

www.acmicpc.net

 

 

[ 문제풀이 ]

 

이 문제를 풀기 전에 다음 글을 먼저 읽어보시는 걸 추천드립니다.

 

https://rudalsd.tistory.com/426

 

1.  $_{n}\textrm{C}_{r} =\,    _{n-1}\textrm{C}_{r-1} +\,  _{n-1}\textrm{C}_{r}$ 이므로 분할정복을 이용하여 $_{n}\textrm{C}_{r}$를 구해줍니다.

 

2. 뤼카의 정리를 이용하여 각각의 조합의 값들을 곱해 M으로 나눈 나머지를 출력합니다.

 

[ 소스 코드 ]

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
#include<vector>
#define ll long long
 
using namespace std;
 
ll N, K;
int M;
ll arr[2001][2001];
 
vector<int> luca(ll N, int M)
{
    vector<int> ret;
 
    while (N) {
        int temp = N % M;
        ret.push_back(temp);
        N /= M;
    }
 
    return ret;
}
 
ll comb(int N, int R)
{
    if (N < R) return 0;
    if (R == 1return N;
    if (R == 0return 1;
    if (arr[N][R] != 0return arr[N][R];
 
    return arr[N][R] = (comb(N - 1, R - 1+ comb(N - 1, R)) % M;
}
 
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    cin >> N >> K >> M;
 
    vector<int> n, k;
 
    n = luca(N, M);
    k = luca(K, M);
 
    int idx = min(n.size(), k.size());
 
    ll ans = 1;
 
    for (int i = 0; i < idx; i++) {
        ans *= comb(n[i], k[i]);
        ans %= M;
        if (ans == 0break;
    }
 
    cout << ans;
}
cs
반응형

+ Recent posts