【模板】卢卡斯定理

题意简述

给定n,m,p (\( 1 <= n,m,p <= 10^5 \))
求 \(C_{n+m}^{m}\ mod\ p \)

题解思路

Lucas定理
\(C^a_b\equiv C^{\lfloor{a / p}\rfloor}_{\lfloor{b / p}\rfloor} \times C^{a\mod p}_{b\mod p} \left(mod\ p\right) \)

代码

#include <cstdio>
#include <algorithm>
typedef long long ll;
int T, n, m, p, l;
int fac[101000], ifac[101000];
int ksm(int x, int y, int s = 1)
{
	for (register int i = y; i; i >>= 1, x = (ll)x * x % p)
		if (i & 1)
			s = (ll)s * x % p;
	return s;
}
int C(int x, int y)
{
	if (y > x) return 0;
	if (x == y) return 1;
	if (x > p || y > p) return (ll)C(x / p, y / p) * C(x % p, y % p) % p;
	return (ll)fac[x] * ifac[x - y] % p * ifac[y] % p;
}
int main()
{
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%d%d", &n, &m, &p);
		fac[0] = ifac[0] = 1;
		l = std::min(n + m, p - 1);
		for (register int i = 1; i <= l; ++i) fac[i] = (ll)fac[i - 1] * i % p;
		ifac[l] = ksm(fac[l], p - 2);
		for (register int i = l - 1; i; --i) ifac[i] = (ll)ifac[i + 1] * (i + 1) % p;
		printf("%d\n", C(n + m, m));
	}
}
posted @ 2018-09-10 18:56  xuyixuan  阅读(529)  评论(0编辑  收藏  举报