首先说下啥是lucas定理:

$\binom n m \equiv \binom {n\%P} {m\%P} \times \binom{n/P}{m/P} \pmod P$

借助这个定理,求$\binom n m$时,若$P$较小,且$n,m$非常大时,我们就可以用这个定理要降低复杂度。

但是这个定理有一些限制,比如说要求$p$是质数,遇到一些毒瘤出题人不太好应对。

当$P$不是质数时,这时就要用到一个叫做扩展lucas定理的东西。

令$P=\prod p_i^{k_i}$。

我们发现,如果对于每一个$p_i^{k_i}$,我们都求出$\binom n m \% p_i^{k_i}$的值,我们就可以用$CRT$将它们合并,以得到最终的$\binom n m$。

下面考虑如何求$\binom n m \% p_i^{k_i}$。

首先考虑组合数的一个性质:

$\binom n m =\dfrac{n!}{m!(n-m)!}$

那么问题就可以归化为求n!及其逆元的问题

我们发现,我们可以考虑求出$n!$,$m!$的逆元,$(n-m)!$的逆元,然后就可以求出组合数了。

直接求的话,会发现$m!$和$(n-m)!$可能求不出逆元,因为$m!$可能会与$p_i^{k_i}$不互质。

我们定义$G(n,p_i)$表示$n!$中素因子$p_i$的个数,定义$F(n,p_i,k_i)=\dfrac{n!}{p_i^{G(n,p_i)}}$。

则有:

$\binom n m =\dfrac{n!}{m!(n-m)!} \equiv \dfrac{F(n,p_i,k_i)p_i^{G(n,p_i)}}{F(m,p_i,k_i)p_i^{G(m,p_i)}\times  F(n-m,p_i,k_i) p_i^{G(n-m,p_i)}} \pmod {p_i^{k_i}}$

考虑如何求函数$F$,我们显然有一种$O(n)$的求法:

$F(n,p_i,k_i)\equiv \prod\limits_{x=1,(x,p_i)=1}^{n}x \times F(n/p_i^{k_i},p_i,k_i) \pmod {p_i^{k_i}}$

但是它依然是$O(n)$的

通过简单观察可以知道,求解F的连乘过程中有关于$p_i^{k_i}$的循环节,我们可以求出循环节的积,然后通过快速幂求解出前面若干个循环节的积的幂,最后乘上末尾非循环节部分的数。

举个例子:当$n=19,p=3,k=2$时:

$F(19,3,2)\equiv 1\times 2\times 4\times 5\times 7\times 8\times 10\times 11\times 13\times 16\times 17\times 19\times F(6,3,2) \pmod{p_i^{k_i}}$

$\equiv (1\times 2\times 4\times 5\times 7\times 8)^2\times 19 \times \pmod{p_i^{k_i}}$

根据这一个性质,我们得到:

$F(n,p_i,k_i)\equiv \left(\prod\limits_{x=1,(n,p_i)=1}^{p_i^{k_i}}\right)^{\left \lfloor n/{p_i^{k_i}} \right \rfloor}     F(n/p_i^{k_i},p_i,k_i) \pmod{p_i^{k_i}}$

当$n=0$时,$F(n)=1$。

考虑如何求函数$G$,我们同样地采用递归的方式来搞,当$n>0$时,有:

$G(n,p_i)=\lfloor \frac{n}{p_i} \rfloor +G(\lfloor \frac{n}{p_i} \rfloor,p_i)$

当$n=0$时,$G$显然为$0$。

至此,我们求出了$\binom n m \% p_i^{k_i}$。

我们求出了若干组这样的方程后,用CRT合并,就得到了最终的答案。

这种做法的复杂度也是非常地玄学,它是:

$O(\sum p^k\log(log_p n-k)+p\log P)$

 #include<bits/stdc++.h>
#define M 20000005
#define L long long
#define INF (1LL<<60)
using namespace std; L pow_mod(L x,L k,const L MOD){L ans=;for(;k;k>>=,x=x*x%MOD) if(k&) ans=ans*x%MOD; return ans;} void exgcd(L a,L b,L &x,L &y){
if(!b) {x=; y=; return;}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
L inv(L a,L MOD){ L res1,res2; exgcd(a,MOD,res1,res2); return (res1+MOD)%MOD;} L getp(L n,L p){L ans=; for(;n;n/=p) ans=ans+n/p; return ans;}
L fac(L n,L p,L k){
if(!n) return ;
L all=pow_mod(p,k,INF),mul=,ans=;
for(L i=;i<all;i++) if(i%p) mul=1LL*mul*i%all;
ans=pow_mod(mul,n/all,all);
for(L i=n%all;i;i--) if(i%p) ans=1LL*ans*i%all;
return 1LL*ans*fac(n/p,p,k)%all;
} L get(L n,L m,L MOD){
L c1=,m1=,p,up;
for(p=,up=sqrt(MOD);p<=up;p++) if(MOD%p==){
loop:;
L k=(p>up),all=(p>up?p:);
while(MOD%p==) k++,MOD/=p,all*=p;
L facn=fac(n,p,k);
L facm=fac(m,p,k);
L facnm=fac(n-m,p,k);
L psum=getp(n,p)-getp(m,p)-getp(n-m,p);
L c2=1LL*facn*inv(facm,all)%all*inv(facnm,all)%all*pow_mod(p,psum,all)%all;
L mm=m1*all;
L x=(1LL*inv(m1,all)*(c2-c1)%mm*m1+c1)%mm;
m1=mm; c1=(x+m1)%m1;
}
if(MOD>){p=MOD; MOD=; goto loop;}
return c1;
} main(){
L z,y,p; cin>>z>>y>>p;
cout<<get(z,y,p)<<endl;
}

【learning】 扩展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. BZOJ - 2142 礼物 (扩展Lucas定理)

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

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

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

  4. Lucas定理和扩展Lucas定理

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

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

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

  6. [笔记] 扩展Lucas定理

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

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

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

  8. 扩展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其次,我们 ...

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

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

随机推荐

  1. Echarts的使用方法

    效果图: 1. 在echarts官网下载包,解压后,将文件Echarts\echarts-2.2.7\echarts-2.2.7\doc\example\www\js\echarts.js文件拷贝,放 ...

  2. Codeforces Round #523 (Div. 2) F. Katya and Segments Sets (交互题+思维)

    https://codeforces.com/contest/1061/problem/F 题意 假设存在一颗完全k叉树(n<=1e5),允许你进行最多(n*60)次询问,然后输出这棵树的根,每 ...

  3. 相似性度量 Aprioir算法

    第三章 标称:转换成0,1来算,或者用非对称二元属性 二元:x1,x2的分布取00,01,10,11的二元属性个数,列表,算比例.不对称的二元属性就忽略00的属性个数 序数:转换成排位rif,度量:r ...

  4. 第15章:MongoDB-聚合操作--聚合管道--$match

    ①$match 用于对文档集合进行筛选,里面可以使用所有常规的查询操作符. 通常会放置在管道最前面的位置,理由如下: 1:快速将不需要的文档过滤,减少后续操作的数据量 2:在投影和分组之前做筛选,查询 ...

  5. 使用jstl的Foreach 和jquery的each()的index属性

    最近项目中用到隔行换色问题,使用到了jstl的foreach和jquery的each进行遍历. 首先jstl技术.除了常用的items,var外,还有一个下标属性varStatus,从0开始,使用起来 ...

  6. thinkphp3.2.3 数据库增删改查

    版本3.23 1. 多表查找一条数据 M('a表')->join("b表 on b表.id=a表.id")->where('条件')->find(); 2.查找一 ...

  7. php mysqli 链接数据库 CURD 增改查删

    <?php function println($msg) { echo "<br>"; echo $msg; } $mysql_server_name = &qu ...

  8. ASP.NET 日志组件Smart.LogNet.DLL 引用即可写入日志及读取日志

    借助LogNet组件,以后查看站点日志,再也不用去服务器下载了 日志组件:LogNet.DLL ,引用即可使用 写入方法: 1.LogNet.Log.WriteLog("日志标题" ...

  9. 阿里ETL工具datax学习(一)

    阿里云开源离线同步工具DataX3.0介绍 一. DataX3.0概览 ​ DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDFS.Hive.Ma ...

  10. 微信官方api & 非官方api

    1.微信公众平台开发者文档 http://mp.weixin.qq.com/wiki/home/index.html 2.微信公众平台 https://mp.weixin.qq.com/ 3.第三方a ...