lucas定理学习
Lucas定理是用来求 c(n,m) mod p,p为素数的值。
- 表达式:
- C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
- 当我们遇到求一个N,M很大的组合数的时候,递推法就显得很耗时了,对于1e9那么大的数据求N!%P,无论是空间还是时间都不会允许。
- 于是引申出lucas定理,利用这个表达式可以将数量级降低好几个,从而减小时间和空间的开销。
- 一般来说可以用lucas定理解决的问题都是N,M很大,但质数P相对来说在1e5左右,不会太大,我们利用迭代渐渐缩小N,M的值,
- 将C(N%P,M%P)累乘在答案上求解,下面来思考怎么编写代码。
这个定理目前我不会证明,只是知道内容,惭愧。
当N,M不为0时且组合数合法我们可以继续迭代,当算出来的N%P<M%P时表示结果为0此时直接返回0即可。
对于一个较小的C(n,m)=n!/(m!*(n-m)!) ,我们就可以根据这个式子得到 C(n,m)%P=f(n)%P*(f(m)*f(n-m))-1%P 其中f表示阶乘
由于P是一个质数,由费马小定理可以得到 (f(m)*f(n-m))-1=mod_pow(f(m)*f(n-m),P-2,P),我们可以先打表出f[P]之内的阶乘对P取余然后直接调用即可。
下面是主要代码:
//lucas定理
LL quick_mod(LL a, LL b, LL c)
{
LL ans = ;
while(b)
{
if(b & )
ans = (ans*a)%c;
b>>=;
a = (a*a)%c;
}
return ans;
}
LL fac[MAXN_P];
void Get_Fac(LL p)///m!
{
fac[] = ;
for(int i=; i<=p; i++)
fac[i] = (fac[i-]*i) % p;
}
LL Lucas(LL n, LL m, LL p) //C(n,m)%p
{
LL ans = ;
while(n && m)
{
LL a = n % p;
LL b = m % p;
if(a < b)
return ;
ans = ( (ans*fac[a]%p) * (quick_mod(fac[b]*fac[a-b]%p,p-,p)) ) % p;
n /= p;
m /= p;
}
下面以51nod 1120为例 , 这是题目链接
是一个经典的求卡特兰数的例题,但是N达到了1e9的规模,如果使用O(N)打表,f[n]=(f[n-1]*(4*n-2))/(n+1)得话时间不允许。
还有另一种递推式子是 f[n]=C(N*2,N)/(N+1) ,所以答案就是二倍的第(N-1)个卡特兰数对10007取余,可以用lucas求解,注意有分母的存在要求一下逆元,
由于N很大,也不能用打表法求逆元,可以用拓展欧几里得或者快速幂(由于这里P是质数且lucas就要用到快速幂,所以快速幂很方便不必要重写exgcd)
参考代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 100005
void gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(!b) {d=a;x=;y=;}
else {gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
LL Inv(LL a,LL n)
{
LL d,x,y;
gcd(a,n,d,x,y);
return d==?(x+n)%n:-;
} LL quick_mod(LL a, LL b, LL c)
{
LL ans = ;
while(b)
{
if(b & )
ans = (ans*a)%c;
b>>=;
a = (a*a)%c;
}
return ans;
}
LL fac[MAXN];
void Get_Fac(LL p)///m!
{
fac[] = ;
for(int i=; i<=p; i++)
fac[i] = (fac[i-]*i) % p;
}
LL Lucas(LL n, LL m, LL p)
{
LL ans = ;
while(n && m)
{
LL a = n % p;
LL b = m % p;
if(a < b)
return ;
ans = ( (ans*fac[a]%p) * (quick_mod(fac[b]*fac[a-b]%p,p-,p)) ) % p;
n /= p;
m /= p;
}
return ans;
}
int main()
{
LL n, m, p=;
Get_Fac(p);
cin>>n;n--;
cout<<Lucas(n*,n,p)**quick_mod(n+,p-,p)/*Inv(n+1,p)*/%p<<endl;
return ;
}
lucas定理学习的更多相关文章
- lucas 定理学习
大致意思就是求组合数C(n , m) % p的值, p为一个偶数 可以将组合数的n 和 m都理解为 p 进制的表示 n = ak*p^k + a(k-1)*p^(k-1) + ... + a1*p ...
- 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定理学习(进阶中)
(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, m, p$,求$C_{n}^{m}$除以$p$后的余数. Subtask#1 $0\leqslant m\leq ...
- Lucas定理学习笔记(没有ex_lucas)
题目链接\(Click\) \(Here\) \(ex\_lucas\)实在是不能学的东西...简单学了一下\(Lucas\)然后打算就这样鸽着了\(QwQ\)(奶一口不可能考) 没什么复杂的,证明的 ...
- [Lucas定理]【学习笔记】
Lucas定理 [原文]2017-02-14 [update]2017-03-28 Lucas定理 计算组合数取模,适用于n很大p较小的时候,可以将计算简化到小于p $ \binom{n}{m} \m ...
- [学习笔记]扩展LUCAS定理
可以先做这个题[SDOI2010]古代猪文 此算法和LUCAS定理没有半毛钱关系. [模板]扩展卢卡斯 不保证P是质数. $C_n^m=\frac{n!}{m!(n-m)!}$ 麻烦的是分母. 如果互 ...
- 【转】Lucas定理 & 逆元学习小结
(From:离殇灬孤狼) 这个Lucas定理是解决组合数的时候用的,当然是比较大的组合数了.比如C(1000000,50000)% mod,这个mod肯定是要取的,要不算出来真的是天文数字了. 对于一 ...
- lucas定理 +证明 学习笔记
lucas定理 p为素数 \[\dbinom n m\equiv\dbinom {n\%p} {m\%p} \dbinom {n/p}{m/p}(mod p)\] 左边一项直接求,右边可递归处理,不包 ...
随机推荐
- sklearn.svm包中的SVC(kernel=”linear“)和LinearSVC的区别
参考:https://stackoverflow.com/questions/45384185/what-is-the-difference-between-linearsvc-and-svckern ...
- 【vim使用】
nano,与vim相似的一个文本编辑工具,在git merge时默认使用 https://www.vpser.net/manage/nano.html 这里介绍一下如何退出nano 按Ctrl+X 如 ...
- python进程间数据不共享(示例演示)
import multiprocessing data_list = [] def task(arg): data_list.append(arg) print(data_list) def run( ...
- django Form表单的使用
Form django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm 关于django的表单系统,主要分两种 基于django.forms.Form ...
- django 通过orm操作数据库
Django Model 每一个Django Model都继承自django.db.models.Model 在Model当中每一个属性attribute都代表一个database field 通过D ...
- MySQL查询操作
查询执行路径中的组件:查询缓存.解析器.预处理器.优化器.查询执行引擎.存储引擎SELECT语句的执行流程: FROM Clause --> WHERE Clause --> GROUP ...
- Java泛型四:Java泛型总结
原文地址https://www.cnblogs.com/lwbqqyumidi/p/3837629.html 一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 publ ...
- Python(文件处理)
二.基本操作 #r''------------------>> r:原生字符串,不判断符号的含义#文件处理 f=open(r’c:\a.txt’,’r’,encoding=’utf-8’) ...
- Cpython-并发编程
阅读目录 一 背景知识 二 python并发编程之多进程 三 python并发编程之多线程 四 python并发编程之协程 五 python并发编程之IO模型 六 补充:paramiko模块 七 作业 ...
- Delphi 正则表达式语法(2): 或者与重复
Delphi 正则表达式语法(2): 或者与重复 // | 号的使用, | 是或者的意思 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create ...