洛谷模板题面:https://www.luogu.org/problemnew/show/P4720

扩展卢卡斯被用于解决模数为合数情形下的组合数问题。

首先我们把模数mod质因数分解,解决模每个素数的幂意义下的组合数这样一个子问题,最后用crt把他们合并到一起。

那么我们现在要解决这样一个问题:

\[C(n,m) \quad mod \quad p^k
\]

其中p为质数。

\(p^k\)可能很大,而且性质与p不同,使用单纯的lucas解决肯定是不行了。

我们考虑把组合数拆成阶乘的形式,发现 $n! ,m! , (n-m)! $都有可能含有质数p,而当分母含有p的时候与模数不互质,逆元是没有办法求的,所以我们必须把p全都提出。

化成这种形式:

\[\frac{\frac{n!}{p^a}}{\frac{m!*(n-m)!}{p^b}}*p^{(a-b)}
\]

发现 去除掉所有p的\(n!\) 是有非常美妙的性质的,它可以提出一段可求长度的去p阶乘,然后剩下一部分是更小规模的阶乘(读者可以试着导一导),有了这个性质,我们便可以递归求解了。预处理出来一些东西后,可以像普通lucas一样简洁,高效。

细节部分详见代码中分解质因数时的预处理部分和Fac函数。

注意:

1、这里求逆元要用exgcd。

2、复杂度与min(n,max_p)有关,当mod比较大n较小时别忘了取min。

接下来是一份AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N =1000005;
#define rep(i,a,b) for(register int i=(a);i<=(b);++i) typedef long long ll;
ll m,n;
int mod;
ll fac[N],inv[N];
ll ksm(ll x,ll y,ll M){
ll aa=1ll;
for(x%=M;y;y>>=1,x=(x*x)%M)if(y&1)aa=(aa*x)%M;
return aa;
}
int p[N],pk[N],cnt;
ll sum,fak[22][N];
ll exgcd(ll x,ll y,ll &a,ll &b){
if(!y){a=1,b=0;return x;}
ll d=exgcd(y,x%y,b,a);
b-=x/y*a;
return d;
}
inline ll Inv(ll x,ll y){
ll inv,rua;
exgcd(x,y,inv,rua);
return (inv+y)%y;
}
ll Fac(ll x,int i){
if(x==0||x==1)return 1;
return Fac(x/p[i],i)*ksm(fak[i][pk[i]-1],x/pk[i],pk[i])%pk[i]*fak[i][x%pk[i]]%pk[i];
}
ll ex_Lucas(ll x,ll y,int i){
if(x<y)return 0;
ll num=0;
for(ll j=x;j;j/=p[i])
num+=j/p[i];
for(ll j=y;j;j/=p[i])num-=j/p[i];
for(ll j=x-y;j;j/=p[i])num-=j/p[i];
return Fac(x,i)*Inv(Fac(y,i),pk[i])%pk[i]*Inv(Fac(x-y,i),pk[i])*ksm(p[i],num,pk[i])%pk[i];
}
ll ans;
int main(){
scanf("%lld%lld%d",&n,&m,&mod);
int x=mod;
for(int i=2;i*i<=mod;++i){
if(x%i==0){
p[++cnt]=i;
pk[cnt]=1;
while(x%i==0)x/=i,pk[cnt]*=i;
sum=1;fak[cnt][0]=1;
rep(j,1,pk[cnt]-1){
if(j%p[cnt])sum=sum*j%pk[cnt];
fak[cnt][j]=sum;
}
}
}
if(x!=1){
++cnt,p[cnt]=pk[cnt]=x;
sum=1;fak[cnt][0]=1;
rep(j,1,pk[cnt]-1){
if(j%p[cnt])sum=sum*j%pk[cnt];
fak[cnt][j]=sum;
}
}
ll tmp;
rep(i,1,cnt){
tmp=ex_Lucas(n,m,i);
ans=(ans+tmp*(mod/pk[i])%mod*Inv(mod/pk[i],pk[i])%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}

【扩展lucas定理】的更多相关文章

  1. 2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理)

    J. Ceizenpok’s formula time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  2. 【learning】 扩展lucas定理

    首先说下啥是lucas定理: $\binom n m \equiv \binom {n\%P} {m\%P} \times \binom{n/P}{m/P} \pmod P$ 借助这个定理,求$\bi ...

  3. BZOJ - 2142 礼物 (扩展Lucas定理)

    扩展Lucas定理模板题(貌似这玩意也只能出模板题了吧~~本菜鸡见识鄙薄,有待指正) 原理: https://blog.csdn.net/hqddm1253679098/article/details ...

  4. [bzoj2142]礼物(扩展lucas定理+中国剩余定理)

    题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod  = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...

  5. Lucas定理和扩展Lucas定理

    1.Lucas定理 首先给出式子:\(C_n^m\%p = C_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor} * C_{n\%p}^{ ...

  6. Ceizenpok’s formula Gym - 100633J 扩展Lucas定理 + 中国剩余定理

    http://codeforces.com/gym/100633/problem/J 其实这个解法不难学的,不需要太多的数学.但是证明的话,我可能给不了严格的证明.可以看看这篇文章 http://ww ...

  7. [笔记] 扩展Lucas定理

    [笔记] 扩展\(Lucas\)定理 \(Lucas\)定理:\(\binom{n}{m} \equiv \binom{n/P}{m/P} \binom{n \% P}{m \% P}\pmod{P} ...

  8. [学习笔记]扩展LUCAS定理

    可以先做这个题[SDOI2010]古代猪文 此算法和LUCAS定理没有半毛钱关系. [模板]扩展卢卡斯 不保证P是质数. $C_n^m=\frac{n!}{m!(n-m)!}$ 麻烦的是分母. 如果互 ...

  9. 扩展Lucas定理

    (1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0,m=[m/p]*p+b0其次,我们 ...

  10. 扩展Lucas定理 扩展Lucas板子

    题意概述:多组询问,给出N,K,M,要求回答C(N,K)%M,1<=N<=10^18,1<=K<=N,2<=M<=10^6 分析: 模数不为质数只能用扩展Lucas ...

随机推荐

  1. COALESCE 函数作用

    用途. 将空值替换成其他值 返回第一个非空值. 任意一个不为空的值.比较有用.

  2. python web自动化测试框架搭建(功能&接口)——环境搭建

    自动化测试框架一般需要实现以下通用功能 执行前准备 结束后清理 执行步骤输出 执行结果输出 错误.失败截图 测试报告 发送邮件 日志 需要的软件和python第三方库有: 通用: JDK Eclips ...

  3. PAT_A1074#Reversing Linked List

    Source: PAT A1074 Reversing Linked List (25 分) Description: Given a constant K and a singly linked l ...

  4. shell zip和unzip压缩和解压,压缩效率

    1.把/home目录下面的mydata目录压缩为mydata.zip zip -r mydata.zip mydata #压缩mydata目录zip -r mydata.zip ./*txt #压缩当 ...

  5. mysql学习(1)----------基础语法

    进入mysql mysql -u用户名 -p密码 初始用户为root   初始密码为空   status; 查看当前用户,以及数据库的字符集和其他参数的设置 set db  characterset= ...

  6. angularJS 入门知识

    模块:模块可以定义自己的控制器.服务.工厂类以及指令 模块可以依赖其他模块 模块两大常见错误: 定义模块的时候忘记第二个参数,变成使用模块而不是定义模块 使用模块的时候忘记引用依赖模块

  7. java并发编程之美-阅读记录4

    java并发包中的原子操作类,这些类都是基于非阻塞算法CAS实现的. 4.1原子变量操作类 AtomicInteger/AtomicLong/AtomicBoolean等原子操作类 AtomicLon ...

  8. jsp与httpservlet的微小区别

    2015-8 jsp与httpservlet的微小区别: jsp默认支持会话,httpservlet默认不支持会话:jsp: 可以直接通过session引用httpservlet对象httpservl ...

  9. 在Linux上搭建私有git仓库

    最近在学Linux,顺便将自己的服务器用起来,不然又得废弃一年.这次是跟着网上的教程做一个简单的git私有仓库,复杂完整的git系统还需使用gitlib系统. 首先在linux上安装git yum i ...

  10. java NIO 详解

    Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.本系列教程将有助于你学习和理解Java NIO. Java NIO提供了与 ...