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

题目链接:luogu P3807

题目大意

求 C(n,n+m)%p 的值。

p 保证是质数。

思路

Lucas 定理内容

对于非负整数 \(n\),\(m\),质数 \(p\),有:

\(C_m^n\equiv \prod\limits_{i=0}^kC_{m_i}^{n^i}(\bmod\ p)\)

其中 \(m=m_kp^k+...+m_1p+m_0\),\(n=n_kp^k+...+n_1p+n_0\)。(其实就是 \(n,m\) 的 \(p\) 进制展开)

那我们一般做题用的是递推式,也就是 \(C_m^n\equiv C_{\left\lfloor m/p\right\rfloor}^{\left\lfloor n/p\right\rfloor}C_{m\bmod p}^{n\bmod p}(\bmod\ p)\)

(当 \(n>m\) 时,我们规定 \(C_{m}^n=0\))

啥时候会用

我们有时候要算组合数,可能 \(C_{m}^n\) 的 \(n,m\) 很大,这时候一般做题就会让他取模一个数 \(\bmod \ p\)。

那如果 \(p>m\),我们可以愉快的用这个式子求:\(C_{m}^n=\dfrac{m!}{n!(m-n)!}\)

算出 \(n!\) 和 \((m-n)!\) 的逆元,就可以搞。

可当 \(m\geqslant p\) 的时候,分母的乘法逆元可能不存在。(因为 \(x\) 是 \(p\) 的倍数的话 \(x\) 就没有模 \(p\) 的逆元)

那这个时候我们就可以用 Lucas 定理把这个组合数拆成几个 \(m<p\) 的,就可以搞了。

证明

证明 Lucas 定理之前,我们先证明两个式子。


式一:

\(C_p^i\equiv \frac{p}{i}C_{p-1}^{i-1}\equiv0(\bmod\ p),(1\leqslant i<p)\)

证明:

\(C_p^i=\dfrac{p!}{i!(p-i)!}=\dfrac{p}{i}\dfrac{(p-1)!}{(i-1)!(p-1-(i-1))!}=\frac{p}{i}C_{p-1}^{i-1}\)

由于 \(1\leqslant i<p\),故 \(i\) 会有 \(p\) 的逆元 \(inv_i\)

\(\frac{p}{i}C_{p-1}^{i-1}=p\times inv_i\times C_{p-1}^{i-1}\)

那这个地方都是 \(p\) 的倍数,那它被 \(p\) 取模一定是 \(0\),故得证。


式二:

根据二项式定理:

\((1+n)^p\equiv C_p^0+C_p^1x+...+C_p^{p-1}x^{p-1}+C_p^px^p(\bmod\ p)\)

再根据式一 \(C_p^i\equiv0(\bmod\ p),(1\leqslant i<p)\),可以得到

\((1+n)^p\equiv C_p^0+C_p^px^p\equiv 1+x^p(\bmod\ p)\)


接着我们开始证明,先设 \(\left\lfloor m/p\right\rfloor=q_m,\left\lfloor n/p\right\rfloor=q_n,m\bmod p=r_m,n\bmod p=r_n\)。

那有 \(m=q_mp+r_m,n=q_np+r_n\)。

接着我们继续用二项式定理:

\((1+x)^m=\sum\limits_{i=1}^{m}C_{m}^ix^i\)

然后我们把左边给化简:

\(\begin{aligned}(1+x)^m & =(1+x)^{q_mp+r_m} \\ & =(1+x)^{q_mp}\cdot(1+x)^{r_m} \\& =[(1+x)^p]^{q_m}\cdot(1+x)^{r_m}\\&\equiv(1+x^p)^{q_m}\cdot(1+x)^{r_m}[式二]\\&\equiv\sum\limits_{i=1}^{q_m}C_{q_m}^ix^{ip}\sum\limits_{i=1}^{r_m}C_{r_m}^{i}x^i(\bmod\ p)\end{aligned}\)

那就有:

\(\sum\limits_{i=1}^{m}C_{m}^ix^i\equiv\sum\limits_{i=1}^{q_m}C_{q_m}^ix^{ip}\sum\limits_{i=1}^{r_m}C_{r_m}^{i}x^i(\bmod\ p)\)

那对于任意一个数 \(z\),必然会有一组 \(i,j\) 满足 \(x^z=x^{pi}x^j\)

不难看出这其实就是满足 \(z=pi+j\),所以当且仅当 \(i=\left\lfloor \dfrac{z}{p}\right\rfloor,j=z\bmod p\)。

那也就是说左边的 \(i\) 取任意一个,右边都有一个新的跟它对于恒等。

左边 \(i=x\),右边的就分别是 \(i=\left\lfloor \dfrac{x}{p}\right\rfloor,i=x\bmod p\)

那当 \(i=x\),就有:

\(\begin{aligned}C_m^nx^n&=C_{q_m}^{q_n}x^{q_np}C_{r_m}^{r_n}x^{r_n}\\C_m^nx^n&=C_{q_m}^{q_n}C_{r_m}^{r_n}x^{q_np+r_n}\\C_m^nx^n&=C_{q_m}^{q_n}C_{r_m}^{r_n}x^n\end{aligned}\)

两边同乘 \(inv(x^n)\),就有了 \(C_{m}^n=C_{q_m}^{q_n}C_{r_m}^{r_n}\)

得证。

本题

其实逆元的话直接要用的话直接 \(x^{p-2}\bmod p\) 更好,不用像我这样线性求出每个。

代码

#include<cstdio>
#define ll long long using namespace std; ll T, n, m, p;
ll jc[100001], inv[100001]; ll ksm(ll x, ll y) {
ll re = 1;
while (y) {
if (y & 1) re = (re * x) % p;
x = (x * x) % p;
y >>= 1;
}
return re;
} ll C(ll x, ll y) {//暴力算组合数
if (x > y) return 0;
return ((jc[y] * inv[x]) % p * inv[y - x]) % p;
} ll work(ll n, ll m) {//Lucas 定理
if (!n) return 1;
return (work(n / p, m / p) * C(n % p, m % p)) % p;
} int main() {
scanf("%lld", &T);
while (T--) {
scanf("%lld %lld %lld", &n, &m, &p);
jc[0] = 1;
for (ll i = 1; i <= p; i++)//预处理阶乘与其逆元
jc[i] = (jc[i - 1] * i) % p;
inv[p - 1] = ksm(jc[p - 1], p - 2);
for (ll i = p - 2; i >= 0; i--)
inv[i] = (inv[i + 1] * (i + 1)) % p; printf("%lld\n", work(n, n + m));
} return 0;
}

【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)的更多相关文章

  1. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  2. Luogu P2742 模板-二维凸包

    Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...

  3. 旋度定理(Curl Theorem)和散度定理(Divergence theorem)

    原文链接 首先说说格林公式(Green's theorem).对于一段封闭曲线,若其围城的区域D为单连通区域(内部任意曲线围城的区域都属于院区域),则有如下公式: 其中其中L为D的边界,取正方向.如果 ...

  4. luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

    luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...

  5. 【luogu P3807 卢卡斯定理】 模板

    题目链接:https://www.luogu.org/problemnew/show/P3807 Lucas定理用来求大组合数对一个质数取模的值,不大于10^5用逆元,大于10^5就用Lucas转化成 ...

  6. luogu P3807 【模板】卢卡斯定理

    求 C(n,n+m)%p C(m,n)%p=C(m%p,n%p)*C(m/p,n/p) #include<cstdio> #include<cstring> #include& ...

  7. 【洛谷P3807】(模板)卢卡斯定理

    卢卡斯定理 把n写成p进制a[n]a[n-1][n-2]…a[0],把m写成p进制b[n]b[n-1][n-2]…b[0],则C(n,m)与C(a[n],b[n])*C(a[n-1],b[n-1])* ...

  8. 洛谷.3807.[模板]卢卡斯定理(Lucas)

    题目链接 Lucas定理 日常水题...sublime和C++字体死活不同步怎么办... //想错int范围了...不要被longlong坑 //这个范围现算阶乘比预处理快得多 #include &l ...

  9. 887. 求组合数 III(模板 卢卡斯定理)

    a,b都非常大,但是p较小 前边两种方法都会超时的  N^2 和NlongN  可以用卢卡斯定理  P*longN*longP     定义: 代码: import java.util.Scanner ...

随机推荐

  1. linux操作系统优化系列-RAID不同阵列模式的选择

    背景 笔者所在的某通信运营商某大数据项目由于应用面临瓶颈需要扩充服务器设备,当初上这个项目的时候,服务器上线前的工作(配置raid,安装操作系统,Infiniband网络调试,系统漏洞安全加固)都是我 ...

  2. CentOS 7磁盘寻找不到,卡在sulogin,造成的开机失败问题--Error getting authority...

    今天早上使用内网gitlab仓库的时候,发现页面无法打开,ssh也无法连接. 到机房接上显示器,发现如下错误: Error getting authority: Error initializing ...

  3. 进入除错模式!进入此模式后,将会出现更多的选项,分别是: · 以基本图形介面安装 CentOS 7 (使用标准显卡来设定安装流程图示); · 救援Centos系统; · 执行内存测试(Run a memory test);

    Centos 7.3 安装 0.0392017.07.14 20:12:09字数 1550阅读 985 Centos 7.3 基于 Red Hat 企业版的源代码的最新版本的 CentOS 7 在今年 ...

  4. JavaScript 实现简易版贪吃蛇(Day_13)

    时光永远在变迁,你始终要丢下过去. 使用语言 JavaScript  概述 运用JavaScript  实现简易版<贪吃蛇>.     Html 页面 1 <!DOCTYPE htm ...

  5. lighttpd 轻量级WEB服务器

    Lighttpd 是一款开源 Web 服务器软件.Lighttpd 安全快速,符合行业标准,适配性强并且针对高配置环境进行了优化.相对于其它的 Web 服务器而言,Lighttpd 占用内存更少:因其 ...

  6. 直击Huawei Mate 40产线背后的华为云IoT智能制造

    摘要:数字孪生?在数字世界找到物理世界的设备! 本文分享自华为云社区<[云驻共创]Huawei Mate 40产线直击之华为云IoT智能制造助力工厂数字化转型>,原文作者:启明. Part ...

  7. EVE-NG 入门教程 (Mac OSX BIg Sur)

    EVE-NG 入门搭建指南 1. 什么是 EVE-NG EVE-NG (Emulate d Virtual Environment) 是一个可以运行虚拟主机.网络设备的模拟器,目前该软件分为了社区版. ...

  8. Python-Redis-常用操作&管道

    常用操作 1.1 delete(*names) ? 1 2 3 4 5 6 7 8 9 # 根据删除redis中的任意数据类型   print(r.get('name')) r.delete('nam ...

  9. TensorFlow指定CPU和GPU方法

    TensorFlow指定CPU和GPU方法 TensorFlow 支持 CPU 和 GPU.它也支持分布式计算.可以在一个或多个计算机系统的多个设备上使用 TensorFlow. TensorFlow ...

  10. 利用NVIDIA-NGC中的MATLAB容器加速语义分割

    利用NVIDIA-NGC中的MATLAB容器加速语义分割 Speeding Up Semantic Segmentation Using MATLAB Container from NVIDIA NG ...