【数学】卢卡斯定理

给定 n , m , p n,m,p n,m,p,其中 n , m n,m n,m 较大, p p p 为质数且不是很大,求
( n m )   m o d   p \dbinom{n}{m}\bmod p (mn)modp
L u c a s \rm Lucas Lucas 定理
( n m ) ≡ ( ⌊ n p ⌋ ⌊ m p ⌋ ) ⋅ ( n   m o d   p m   m o d   p ) ( m o d p ) ( p 为 质 数 ) \dbinom{n}{m}\equiv\dbinom{\left\lfloor\frac{n}{p}\right\rfloor}{\left\lfloor\frac{m}{p}\right\rfloor}\cdot \dbinom{n\bmod p}{m\bmod p}\pmod p(p 为质数) (mn)(pmpn)(mmodpnmodp)(modp)p

引理 1 1 1

观察
( p n ) ≡ p ! ( p − n ) ! ⋅ n ! ( m o d p ) \dbinom{p}{n}\equiv\dfrac{p!}{(p-n)!\cdot n!}\pmod p (np)(pn)!n!p!(modp)
分子含有质因数 p p p,所以当分母不含质因数 p p p 时答案为 0 0 0

否则,仅当 n = 0 n=0 n=0 n = p n=p n=p 时分母也含有质因数 p p p,答案为 p ! p ! ⋅ 0 ! = 1 \dfrac{p!}{p!\cdot 0!}=1 p!0!p!=1

引理 2 2 2

考虑这样一个式子
( a + b ) p (a+b)^p (a+b)p
根据二项式定理,这个就是
∑ i = 0 p ( p i ) a i b p − i \sum\limits_{i=0}^{p}\dbinom{p}{i}a^i b^{p-i} i=0p(ip)aibpi
由引理 1 1 1,只有 i = 0 i=0 i=0 i = p i=p i=p ( p i ) \dbinom{p}{i} (ip) 在模 p p p 的意义下值为 1 1 1,所以

( a + b ) p ≡ a 0 b p + a p b 0 ≡ a p + b p ( m o d p ) \begin{aligned} (a+b)^p &\equiv a^0 b^p+a^p b^0\\ &\equiv a^p+b^p\pmod p \end{aligned} (a+b)pa0bp+apb0ap+bp(modp)
那么
( a x + b y ) p ≡ a p x p + b p y p ( m o d p ) (ax+by)^p\equiv a^p x^p+b^p y^p\pmod p (ax+by)papxp+bpyp(modp)
由费马小定理得

a p x p + b p y p ≡ a x p + b y p ( m o d p ) a^p x^p+b^p y^p\equiv a x^p+b y^p\pmod p apxp+bpypaxp+byp(modp)

就是说可以直接把指数 p p p​ 往里乘。

证明:

( x + 1 ) n (x+1)^n (x+1)n 中的项 x m x^m xm 的系数模 p p p,根据二项式定理就是 ( n m )   m o d   p \dbinom{n}{m}\bmod p (mn)modp ( 1 ) \quad(1) (1)

又根据引理 2 2 2
( x + 1 ) n ≡ ( x + 1 ) p ⌊ n p ⌋ ( x + 1 ) n   m o d   p ≡ ( x p + 1 p ) ⌊ n p ⌋ ( x + 1 ) n   m o d   p ≡ ( x p + 1 ) ⌊ n p ⌋ ( x + 1 ) n   m o d   p ( m o d p ) \begin{aligned} (x+1)^n &\equiv (x+1)^{p\left\lfloor\frac{n}{p}\right\rfloor}(x+1)^{n\bmod p}\\ &\equiv (x^p+1^p)^{\left\lfloor\frac{n}{p}\right\rfloor}(x+1)^{n\bmod p}\\ &\equiv (x^p+1)^{\left\lfloor\frac{n}{p}\right\rfloor}(x+1)^{n\bmod p}\pmod p \end{aligned} (x+1)n(x+1)ppn(x+1)nmodp(xp+1p)pn(x+1)nmodp(xp+1)pn(x+1)nmodp(modp)

我们发现:

  1. ( x p + 1 ) ⌊ n p ⌋ (x^p+1)^{\left\lfloor\frac{n}{p}\right\rfloor} (xp+1)pn 中的各项的次数均为 p p p 的倍数。

  2. ( x + 1 ) n   m o d   p (x+1)^{n\bmod p} (x+1)nmodp 中的各项的次数最多为 p − 1 p-1 p1

注意到第 2 2 2 条,次数最多只能到 p − 1 p-1 p1,所以要想得到 x m x^m xm,只有一种方法:令 m = p q + r ( r < p ) m=pq+r(r<p) m=pq+r(r<p),则在 ( x p + 1 ) ⌊ n p ⌋ (x^p+1)^{\left\lfloor\frac{n}{p}\right\rfloor} (xp+1)pn 中取到 q q q(即 ⌊ m p ⌋ \left\lfloor\frac{m}{p}\right\rfloor pm)个 x p x^p xp,然后在 ( x + 1 ) n   m o d   p (x+1)^{n\bmod p} (x+1)nmodp 取到 r r r(即 m   m o d   p m\bmod p mmodp)个 x x x

方法数为 ( ⌊ n p ⌋ q ) ⋅ ( n   m o d   p r ) ≡ ( ⌊ n p ⌋ ⌊ m p ⌋ ) ⋅ ( n   m o d   p m   m o d   p ) ( m o d p ) ( 2 ) \dbinom{\left\lfloor\frac{n}{p}\right\rfloor}{q}\cdot\dbinom{n\bmod p}{r}\equiv\dbinom{\left\lfloor\frac{n}{p}\right\rfloor}{\left\lfloor\frac{m}{p}\right\rfloor}\cdot\dbinom{n\bmod p}{m\bmod p}\pmod p\quad(2) (qpn)(rnmodp)(pmpn)(mmodpnmodp)(modp)(2)

( 1 ) ( 2 ) (1)(2) (1)(2) 可得
( n m ) ≡ ( ⌊ n p ⌋ ⌊ m p ⌋ ) ⋅ ( n   m o d   p m   m o d   p ) ( m o d p ) \dbinom{n}{m}\equiv \dbinom{\left\lfloor\frac{n}{p}\right\rfloor}{\left\lfloor\frac{m}{p}\right\rfloor}\cdot \dbinom{n\bmod p}{m\bmod p}\pmod p (mn)(pmpn)(mmodpnmodp)(modp)

证毕。

P3807 【模板】卢卡斯定理/Lucas 定理

预处理处 ∀ i ∈ [ 0 , p ) \forall i\in[0,p) i[0,p) i ! i! i! i n v ( i ! ) inv(i!) inv(i!)。然后对于单个询问, ( ⌊ n p ⌋ ⌊ m p ⌋ ) \dbinom{\left\lfloor\frac{n}{p}\right\rfloor}{\left\lfloor\frac{m}{p}\right\rfloor} (pmpn) 部分递归去跑,因为 p ≥ 2 p\ge 2 p2,所以是 log ⁡ n \log n logn 的, ( n   m o d   p m   m o d   p ) \dbinom{n\bmod p}{m\bmod p} (mmodpnmodp) 部分就是预处理的。

时间复杂度为 O ( p + T log ⁡ n ) \mathcal{O}(p+T\log n) O(p+Tlogn),其中 T T T 为询问次数。

可以发现瓶颈在于线性的预处理,所以 p p p 不能太大。

Code \text{Code} Code

//18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
typedef long long ll;
using namespace std;

const int MAXN = 1e5 + 5;


int p;

int qpow(int a, int b)
{
	int base = a, ans = 1;
	while (b)
	{
		if (b & 1)
		{
			ans = (ll)ans * base % p;
		}
		base = (ll)base * base % p;
		b >>= 1;
	}
	return ans;
}

int inv(int a)
{
	return qpow(a, p - 2);
}

int fac[MAXN], inv_fac[MAXN];

void init()
{
	fac[0] = 1;
	for (int i = 1; i < p; i++)
	{
		fac[i] = (ll)fac[i - 1] * i % p;
	}
	inv_fac[p - 1] = inv(fac[p - 1]);
	for (int i = p - 2; i >= 0; i--)
	{
		inv_fac[i] = (ll)inv_fac[i + 1] * (i + 1) % p;
	}
}

int C(int n, int m)
{
	if (m > n)
	{
		return 0;
	}
	return (ll)fac[n] * inv_fac[n - m] % p * inv_fac[m] % p;
}

int Lucas(int n, int m)
{
	if (!m)
	{
		return 1;
	}
	return (ll)Lucas(n / p, m / p) * C(n % p, m % p) % p;
}

int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, m;
		scanf("%d%d%d", &n, &m, &p);
		init();
		printf("%d\n", Lucas(n + m, n));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值