Lucas定理
其中是质数。
当和
比较大但
较小时,可以使用Lucas定理快速计算组合数。
证明
的一种意义是
的
次项系数。在模
意义下,
这是由于在
时都是
的倍数。
因此,的
次系数一定是由
的
次系数和
的
次系数提供的,定理得证。
代码 (BZOJ 2982)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 10007;
int fac[MOD], ifac[MOD];
int sqr(int x) { return x * x % MOD; }
int qpow(int a, int b) { return b ? sqr(qpow(a, b / 2)) * (b & 1 ? a : 1) % MOD : 1; }
int inv(int x) { return qpow(x, MOD - 2); }
void init()
{
fac[0] = 1;
for (int i = 1; i < MOD; i++) fac[i] = fac[i - 1] * i % MOD;
ifac[MOD - 1] = inv(fac[MOD - 1]);
for (int i = MOD - 1; i; i--) ifac[i - 1] = ifac[i] * i % MOD;
}
int combs(int a, int b)
{
if (a < b) return 0;
return fac[a] * ifac[b] % MOD * ifac[a - b] % MOD;
}
int comb(int a, int b)
{
return b ? combs(a % MOD, b % MOD) * comb(a / MOD, b / MOD) % MOD : 1;
}
int main()
{
init();
int T; scanf("%d", &T);
for (int i = 1; i <= T; i++)
{
int n, m; scanf("%d%d", &n, &m);
printf("%d\n", comb(n, m));
}
}