首先说下啥是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. select 选中是否包含

    $("#regionname1").find("option:contains('"+regionname+"')").prop(" ...

  2. hadoop学习笔记-目录

    以下是hadoop学习笔记的顺序: hadoop学习笔记(一):概念和组成 hadoop学习笔记(二):centos7三节点安装hadoop2.7.0 hadoop学习笔记(三):hdfs体系结构和读 ...

  3. mouseover和mouseout事件的相关元素

    在发生mouseover和mouseout事件时,还会涉及更多的元素,这两个事件都会涉及把鼠标指针从一个元素的边界之内移动到另一个元素的边界之内.对mouseover事件而言,事件的主目标获得光标元素 ...

  4. Mathtype批量修改公式

    (1)将模板中的公式直接打开 (2)将需要修改好的公式复制黏贴到模板中 (3)再复制黏贴出,即可 PS: (1)统一设置公式格式 (2)统一设置公式大小

  5. Django工程搭建

    -----环境安装 1.创建虚拟环境 mkvirtualenv django_py3_1.11 -p python3   2.安装django pip install django==1.11.11 ...

  6. Matlab用mpeaks函数求峰值点坐标

    clear;clc;close all % 初始化 m = [-6,-2,0,2,4,6]; sigma = [1,1,0.5,0.25,0.6,2]; h = [1,2,3,2,2.13,3.14] ...

  7. noip第29课作业

    1.   钢条切割 [问题描述] 一家公司购买长钢条,将其切割成短钢条出售,切割本身没有成本,长度为i的短钢条的价格为Pi.那给定一段长度为n的钢条和一个价格表Pi,求钢条的切割方案使得收益Rn最大. ...

  8. request.getScheme() 使用方法

    今天在看代码时,发现程序使用了 request.getScheme() .不明白是什么意思,查了一下.结果整理如下: 1.request.getScheme() 返回当前链接使用的协议:一般应用返回h ...

  9. [mysql]当mysql查询语句查询的结果为空时,返回query结果是什么类型的呢?

    php > $con = mysql_connect('localhost' , 'hnb' , 'alyHnb2015'); php > print_r($con);Resource i ...

  10. iOS之UITextField限制字数

    解决方法:根据UITextField本身提供的事件监听: [textField addTarget:self action:@selector(textFieldDidChange:) forCont ...