扩展卢卡斯定理

求 \(C_n^m \bmod{p}\),其中 \(C\) 为组合数。

\(1≤m≤n≤10^{18},2≤p≤1000000\) ,不保证 \(p\) 是质数

Fading的题解

\[p=p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_k^{\alpha_k}
\]

求出

\[\left\{\begin{align*}
C_n^m & \mod & {p_1^{\alpha_1}} \\
C_n^m & \mod & {p_2^{\alpha_2}}\\
\vdots\\
C_n^m & \mod & {p_k^{\alpha_k}}
\end{align*} \right.
\]

最后用中国剩余定理合并即可。

假设我们现在要求

\[C_n^m\bmod{P^k}\\
=\frac {n!}{m!(n-m)!}\bmod{P^k}
\]

我们无法求得\(m!,(n-m)!\)的逆元,理由很简单,不一定有解。

怎么办呢?发现\(a\)对\(p\)有逆元的充要条件为\(gcd(a,p)=1\)。所以我们换一个式子:

\[\frac {\frac {n!}{P^{x}}}{\frac {m!}{P^{y}}\frac {(n-m)!}{P^{z}}}P^{x-y-z}\bmod{P^k}
\]

其中\(x\)为\(n!\)中\(P\)因子的个数(包含多少\(P\)因子)。其他都是同理的。

所以如果我们对于一个\(n\),可以求出\(\frac {n!}{P^x}\),那不就完事了吗?(这样我们就可以求逆元了)

问题等价于求\(\frac {n!}{P^x}\bmod{P^k}\)。我们对\(n!\)进行变形:

\[n!=1\cdot 2\cdot 3\cdots n=(P\cdot 2P\cdot 3P\cdots)(1\cdot 2\cdots)
\]

左边是\(1\sim n\)中所有\(\leq n\)的\(P\)的倍数,右边是其它剩余的。

因为\(1\sim n\)中有\(\lfloor \frac nP\rfloor\)个\(P\)的倍数,

\[\therefore\ P^{\lfloor \frac nP\rfloor}(1 \cdot 2 \cdot 3\cdots)(1\cdot 2\cdots)
=P^{\lfloor \frac nP\rfloor}(\lfloor \frac nP\rfloor)!\prod_{i=1,i\not\equiv 0\pmod {P}}^ni
\]

显然后面这个\(\bmod\ P\)是有循环节的。

\[=P^{\lfloor \frac nP\rfloor}(\lfloor \frac nP\rfloor)!(\prod_{i=1,i\not\equiv 0\pmod {P}}^{P^k}i)^{\lfloor \frac n{P^k}\rfloor}(\prod_{i=P^k\lfloor \frac n{P^k}\rfloor,i\not\equiv 0\pmod {P}}^ni)
\]

其中\((\prod_{i=1,i\not\equiv 0\pmod {P}}^{P^k}i)^{\lfloor \frac n{P^k}\rfloor}\)是循环节\(1\sim P\)中所有无\(P\)因子数的乘积,\((\prod_{i=P^k\lfloor \frac n{P^k}\rfloor,i\not\equiv 0\pmod {P}}^ni)\)是余项的乘积。

比如

\[22!\equiv(1\cdot 2\cdot 4\cdot 5\cdot 7\cdot 8)(10\cdot 11\cdot 13\cdot 14\cdot 16\cdot 17)(19\cdot 20\cdot 22)(3\cdot 6\cdot 9\cdot 12\cdot 15\cdot 18\cdot 21)\pmod {3^2}\\
\equiv(1\cdot 2\cdot 4\cdot 5\cdot 7\cdot 8)^2(19\cdot 20\cdot 22)3^7(1\cdot 2\cdot 3\cdot 4\cdot 5\cdot 6\cdot 7)\pmod {3^2}\\
\equiv3^77!(1\cdot 2\cdot 4\cdot 5\cdot 7\cdot 8)^2(19\cdot 20\cdot 22)\pmod {3^2}
\]

正好是一样的,$\lfloor \frac {22}{3^2}\rfloor=2 $。理解了吧...

发现前面这个\(P^{\lfloor \frac nP\rfloor}\)是要除掉的,然而\((\lfloor \frac nP\rfloor)!\)里可能还包含\(P\)。

所以,我们定义函数:

\[f(n)=\frac {n!}{P^x}\\
=f(\lfloor \frac nP\rfloor)(\prod_{i=1,i\not\equiv 0\pmod {P}}^{P^k}i)^{\lfloor \frac n{P^k}\rfloor}(\prod_{i=P^k\lfloor \frac n{P^k}\rfloor,i\not\equiv 0\pmod {P}}^ni))
\]

这样就好了。时间复杂度是\(O(\log_{P}n)\)。边界\(f(0)=1\)。

看看原式

\[\frac {\frac {n!}{P^{x}}}{\frac {m!}{P^{y}}\frac {(n-m)!}{P^{z}}}P^{x-y-z}\bmod{P^k}\\
=\frac {f(n)}{f(m)f(n-m)}P^{x-y-z}\bmod{P^k}
\]

由于\(f(m)\)一定与\(P^k\)互质,所以我们可以直接用\(exgcd\)求逆元啦。

最后我们还有一个问题,\(P^{x-y-z}\)咋求?其实很好求。

比如说,我们要求\(f(n)=\frac {n!}{P^x}\)中的\(x\)。

设\(g(n)=x\)(上述的\(x\)),再看看阶乘的式子

\[n!=P^{\lfloor \frac nP\rfloor}(\lfloor \frac nP\rfloor)!(\prod_{i=1,i\not\equiv 0\pmod {P}}^{P^k}i)^{\lfloor \frac n{P^k}\rfloor}(\prod_{i=P^k\lfloor \frac n{P^k}\rfloor,i\not\equiv 0\pmod {P}}^ni)
\]

很显然我们要的就是\(P^{\lfloor \frac nP\rfloor}\),而且\((\lfloor \frac nP\rfloor)!\)可能还有\(P\)因子,所以我们可以得到以下递推式

\[g(n)=\lfloor \frac nP\rfloor+g(\lfloor \frac nP\rfloor)
\]

时间复杂度是\(O(\log_{P}n)\)。边界\(g(n)=0(n<P)\)

所以答案就是

\[\frac {\frac {n!}{P^{x}}}{\frac {m!}{P^{y}}\frac {(n-m)!}{P^{z}}}P^{g(x)-g(y)-g(z)}\bmod{P^k}
\]

最后用中国剩余定理合并答案即可得到\(C_n^m\)。总时间复杂度\(O(P \log P)\)。

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T> il T read(T&x){
return x=read<T>();
}
using namespace std;
#define int long long #define gcd __gcd
int pow(int a,int b,int mod){
a=(a%mod+mod)%mod;
int ans=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1) ans=ans*a%mod;
return ans;
}
void exgcd(int a,int b,int&x,int&y){
if(!b) x=1,y=0;
else exgcd(b,a%b,y,x),y-=a/b*x;
}
int inv(int a,int mod){
if(!a) return 0;
if(gcd(a,mod)!=1) return -1;
int x,y;
exgcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
int fac(int n,int pi,int pk){ //n! % pi^ki pk=pi^ki
if(n<=1) return 1;
int ans=1;
for(int i=2;i<pk;++i)
if(i%pi) ans=ans*i%pk;
ans=pow(ans,n/pk,pk);
for(int i=2;i<=n%pk;++i)
if(i%pi) ans=ans*i%pk;
return ans*fac(n/pi,pi,pk)%pk;
}
int binom(int n,int m,int pi,int pk){
int up=fac(n,pi,pk),dl=fac(m,pi,pk),dr=fac(n-m,pi,pk);
int ex=0;
for(int i=n;i;i/=pi) ex+=i/pi;
for(int i=m;i;i/=pi) ex-=i/pi;
for(int i=n-m;i;i/=pi) ex-=i/pi;
return up*inv(dl,pk)%pk*inv(dr,pk)%pk*pow(pi,ex,pk)%pk;
}
signed main(){
int n=read<int>(),m=read<int>(),P=read<int>();
int ans=0,p=P;
for(int i=2;i<=p;++i)if(p%i==0){
int pi=i,pk=1;
while(p%i==0) p/=i,pk*=i;
ans=(ans+binom(n,m,pi,pk)*(P/pk)%P*inv(P/pk,pk)%P)%P;
}
printf("%lld\n",ans);
return 0;
}

LG4720 【模板】扩展卢卡斯定理的更多相关文章

  1. bzoj2142 礼物——扩展卢卡斯定理

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2142 前几天学了扩展卢卡斯定理,今天来磕模板! 这道题式子挺好推的(连我都自己推出来了) , ...

  2. 【知识总结】扩展卢卡斯定理(exLucas)

    扩展卢卡斯定理用于求如下式子(其中\(p\)不一定是质数): \[C_n^m\ mod\ p\] 我们将这个问题由总体到局部地分为三个层次解决. 层次一:原问题 首先对\(p\)进行质因数分解: \[ ...

  3. 【Luogu3807】【模板】卢卡斯定理(数论)

    题目描述 给定\(n,m,p(1≤n,m,p≤10^5)\) 求 \(C_{n+m}^m mod p\) 保证\(P\)为\(prime\) \(C\)表示组合数. 一个测试点内包含多组数据. 输入输 ...

  4. 卢卡斯定理&扩展卢卡斯定理

    卢卡斯定理 求\(C_m^n~mod~p\) 设\(m={a_0}^{p_0}+{a_1}^{p_1}+\cdots+{a_k}^{p_k},n={b_0}^{p_0}+{b_1}^{p_1}+\cd ...

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

    P3807 [模板]卢卡斯定理 求 \(C_{m + n}^{m} \% p\) ( \(1\le n,m,p\le 10^5\) ) 错误日志: 数组开小(哇啊啊啊洼地hi阿偶我姑父阿贺佛奥UFO爱 ...

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

    P3807 [模板]卢卡斯定理 题目背景 这是一道模板题. 题目描述 给定n,m,p(1\le n,m,p\le 10^51≤n,m,p≤105) 求 C_{n+m}^{m}\ mod\ pCn+mm ...

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

    P3807 [模板]卢卡斯定理 洛谷智推模板题,qwq,还是太弱啦,组合数基础模板题还没做过... 给定n,m,p($1\le n,m,p\le 10^5$) 求 $C_{n+m}^{m}\ mod\ ...

  8. 【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)

    [模板]卢卡斯定理/Lucas 定理 题目链接:luogu P3807 题目大意 求 C(n,n+m)%p 的值. p 保证是质数. 思路 Lucas 定理内容 对于非负整数 \(n\),\(m\), ...

  9. 【刷题】洛谷 P3807 【模板】卢卡斯定理

    题目背景 这是一道模板题. 题目描述 给定\(n,m,p( 1\le n,m,p\le 10^5)\) 求 \(C_{n+m}^{m}\ mod\ p\) 保证 \(p\) 为prime \(C\) ...

随机推荐

  1. ObjectARX创建带文字的线型实例代码

    AcDbLinetypeTable* pLinetypeTable=NULL; Acad::ErrorStatus es = acdbHostApplicationServices()->wor ...

  2. docker安装+docker-compose

    1.docker安装 yum install -y yum-utils device-mapper-persistent-data yum-config-manager --add-repo http ...

  3. junit单元测试不通过报documentationPluginsBootstrapper相关异常

    这是因为Spring整合springfox-swagger2后导致的,错误信息如下: -- ::, [main] [WARN] [org.springframework.context.support ...

  4. pycharm django使用技巧

  5. STL对map排序

    // sort start typedef struct{ ... }Node; // Map的键是字符串,值是结构体.虽然有自动排序特性,但是按字符串的排序并不能符合要求.此时,Map的key可以视 ...

  6. Android--Facebook Login with LoginButton

    1.Layout文件添加Facebook的LoginBurtton <com.facebook.widget.LoginButton android:id="@+id/authButt ...

  7. Docker入门以及常用命令

    目的: Docker入门 Docker简介 Centos7安装Docker Docker HelloWorld运行原理解析 阿里云镜像仓库配置 Docker常用命令 Docker基本命令 Docker ...

  8. mysql数据库优化实战--日期及IP地址的正确存储方式

  9. Java线程同步类容器和并发容器(四)

    同步类容器都是线程安全的,在某些场景下,需要枷锁保护符合操作,最经典ConcurrentModifiicationException,原因是当容器迭代的过程中,被并发的修改了内容. for (Iter ...

  10. docker 入坑1

    本文是记录一下学习docker的过程,希望可以帮助到入门的朋友. 系统:ubuntu16.04 docker:18.09 打开官网:https://docs.docker.com/install/li ...