【learning】 扩展lucas定理
首先说下啥是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定理的更多相关文章
- 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 ...
- BZOJ - 2142 礼物 (扩展Lucas定理)
扩展Lucas定理模板题(貌似这玩意也只能出模板题了吧~~本菜鸡见识鄙薄,有待指正) 原理: https://blog.csdn.net/hqddm1253679098/article/details ...
- [bzoj2142]礼物(扩展lucas定理+中国剩余定理)
题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...
- Lucas定理和扩展Lucas定理
1.Lucas定理 首先给出式子:\(C_n^m\%p = C_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor} * C_{n\%p}^{ ...
- Ceizenpok’s formula Gym - 100633J 扩展Lucas定理 + 中国剩余定理
http://codeforces.com/gym/100633/problem/J 其实这个解法不难学的,不需要太多的数学.但是证明的话,我可能给不了严格的证明.可以看看这篇文章 http://ww ...
- [笔记] 扩展Lucas定理
[笔记] 扩展\(Lucas\)定理 \(Lucas\)定理:\(\binom{n}{m} \equiv \binom{n/P}{m/P} \binom{n \% P}{m \% P}\pmod{P} ...
- [学习笔记]扩展LUCAS定理
可以先做这个题[SDOI2010]古代猪文 此算法和LUCAS定理没有半毛钱关系. [模板]扩展卢卡斯 不保证P是质数. $C_n^m=\frac{n!}{m!(n-m)!}$ 麻烦的是分母. 如果互 ...
- 扩展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其次,我们 ...
- 扩展Lucas定理 扩展Lucas板子
题意概述:多组询问,给出N,K,M,要求回答C(N,K)%M,1<=N<=10^18,1<=K<=N,2<=M<=10^6 分析: 模数不为质数只能用扩展Lucas ...
随机推荐
- msyql 主从配置
vim /etc/mysql/my.cnf; # 以下部分一定要配置在[mysqld]后面 [mysqld] log-bin=mysql-bin server-id= //设置数据库服务器唯一ID,这 ...
- 深度优先搜索DFS和广度优先搜索BFS
DFS简介 深度优先搜索,一般会设置一个数组visited记录每个顶点的访问状态,初始状态图中所有顶点均未被访问,从某个未被访问过的顶点开始按照某个原则一直往深处访问,访问的过程中随时更新数组visi ...
- str.index()与str.find()比较
def extract_from_tag(tag,line): opener = "<" + tag + ">" closer = "&l ...
- 查询正在执行的SQL语句DBCCINPUTBUFFER
DBCC INPUTBUFFER 返回进程下SQL语句 如果查询所有的进程如何呢? 创建一个存储过程 CREATE proc pr_dbccINPUTBUFFER(@spid varchar(200) ...
- java学习2打架代码编写
在同一个包中的Player类 package work; public class Player { private String name; private int hp; private int ...
- Nginx使用(配置开机启动)
环境: 系统:CentOS 6.5 Final 安装目录:/usr/local/nginx Nginx开机自启: ①编写shell实现控制 vi /etc/init.d/nginx 添加内容: #!/ ...
- 深入浅出javascript(三)封装和继承
一.私有变量和公有变量 通过var修饰的是私有变量. 二.私有变量的访问方法 三.特权.公有和私有方法 一个例子: function f(name) { var name=name; //私有变量 t ...
- 深入浅出javascript(二)函数和this对象
一.函数对象的属性和方法 函数是一种数据类型,也是对象,这一点很明确.因此,函数对象也可以添加属性和方法,但是这里的属性和方法是静态的,之所以这样说,就是为了区别构造函数. 示例如下: ①创建一个空的 ...
- Shell编程-09-Shell中的函数
目录 基本语法 函数执行 函数示例 函数可以简化程序的代码量,达到更好的代码复用度,因此会让程序变得更加易读.简洁和易修改.其作用就是将需要多次使用的代码整合到一块,使其成为一个整体,然后通过 ...
- (树状数组+离散化)lines--hdu --5124
http://acm.hdu.edu.cn/showproblem.php?pid=5124 lines Time Limit: 5000/2500 MS (Java/Others) Memor ...