卢卡斯定理
Lucas 定理
Lucas定理主要用于模数为质数的大组合数的计算,其内容为
Note
\[\binom{n}{m} \equiv \binom{n \mod p}{m \mod p} \times \binom{\left\lfloor n/p\right\rfloor }{\left\lfloor m/p\right\rfloor } \pmod{p}\]
因此我们可以递归求解组合数,代码如下:
P3807 【模板】卢卡斯定理/Lucas 定理
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 | #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
ll frac[MAXN], p;
ll qpow(ll a, ll b)
{
ll res = 1;
for (; b; b >>= 1, a = a * a % p)
if (b & 1)
res = res * a % p;
return res;
}
ll c(ll n, ll m)
{
if (m > n)
return 0;
return frac[n] * qpow(frac[n - m], p - 2) % p * qpow(frac[m], p - 2) % p;
}
ll lucas(ll n, ll m)
{
if (!m)
return 1;
return lucas(n / p, m / p) * c(n % p, m % p) % p;
}
ll solve()
{
ll n, m;
cin >> n >> m >> p;
n += m;
for (int i = 1; i <= p; i++)
frac[i] = frac[i - 1] * i % p;
return lucas(n, m);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
frac[0] = 1;
int T;
cin >> T;
while (T--)
cout << solve() << endl;
return 0;
}
|