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定理学习的更多相关文章

  1. lucas 定理学习

    大致意思就是求组合数C(n , m) % p的值, p为一个偶数 可以将组合数的n 和 m都理解为 p 进制的表示 n  = ak*p^k + a(k-1)*p^(k-1) + ... + a1*p ...

  2. 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其次,我们 ...

  3. 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其次,我们 ...

  4. Lucas定理学习笔记

    从这里开始 一个有趣的问题 扩展Lucas算法 一个有趣的问题 题目大意 给定$n, m, p$,求$C_{n}^{m}$除以$p$后的余数. Subtask#1  $0\leqslant m\leq ...

  5. Lucas定理学习笔记(没有ex_lucas)

    题目链接\(Click\) \(Here\) \(ex\_lucas\)实在是不能学的东西...简单学了一下\(Lucas\)然后打算就这样鸽着了\(QwQ\)(奶一口不可能考) 没什么复杂的,证明的 ...

  6. [Lucas定理]【学习笔记】

    Lucas定理 [原文]2017-02-14 [update]2017-03-28 Lucas定理 计算组合数取模,适用于n很大p较小的时候,可以将计算简化到小于p $ \binom{n}{m} \m ...

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

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

  8. 【转】Lucas定理 & 逆元学习小结

    (From:离殇灬孤狼) 这个Lucas定理是解决组合数的时候用的,当然是比较大的组合数了.比如C(1000000,50000)% mod,这个mod肯定是要取的,要不算出来真的是天文数字了. 对于一 ...

  9. lucas定理 +证明 学习笔记

    lucas定理 p为素数 \[\dbinom n m\equiv\dbinom {n\%p} {m\%p} \dbinom {n/p}{m/p}(mod p)\] 左边一项直接求,右边可递归处理,不包 ...

随机推荐

  1. VC++SDK编程——鼠标的应用示例

    #include <Windows.h> #include <tchar.h> BOOLEAN InitWindowClass(HINSTANCE hInstance, int ...

  2. tpot从elastic search拉攻击数据之三 用于拉取的java程序

    package download; import org.json.JSONArray; import java.io.*; import java.net.URL; import java.net. ...

  3. 我的Android进阶之旅------>解决Jackson、Gson解析Json数据时,Json数据中的Key为Java关键字时解析为null的问题

    1.问题描述 首先,需要解析的Json数据类似于下面的格式,但是包含了Java关键字abstract: { ret: 0, msg: "normal return.", news: ...

  4. asp.net Mvc Npoi 导出导入 excel

    因近期项目遇到所以记录一下: 首先导出Excel : 首先引用NPOI包 http://pan.baidu.com/s/1i3Fosux (Action一定要用FileResult) /// < ...

  5. 阿里云上Docker Compose部署wordpress

    先上官方文档: https://docs.docker.com/compose/wordpress/ 我的环境: [root@xyjk1002 ~]# cat /etc/redhat-release ...

  6. c# 图片加密解密的实例代码

    c# 图片加密解密的实例代码. 代码: using System; using System.Collections.Generic; using System.Text; using System. ...

  7. PHP获取与操作php.ini文件的几个函数示例

    php有一套设置和获取配置信息的函数,用于设置与修改相关参数信息.   1.ini_get()获取配置参数,ini_set()设置配置参数 <?php 2.ini_get_all()获取所有配置 ...

  8. BOM对象,math对象document对象的属性和操作和 事件的基本操作

    Math对象 //该对象中的属性方法 和数学有关. abs(x) 返回数的绝对值. exp(x) 返回 e 的指数. floor(x) 对数进行下舍入. log(x) 返回数的自然对数(底为e). m ...

  9. 数据结构&算法(二)_算法基础之前传(递归、时间复杂度、空间复杂度、二分查找)

    什么是算法: 间而言之算法(Algorithm):一个计算过程,解决问题的方法 递归的两个特点: 调用自身 结束条件 递归示例: def func(x): : print("我的小鲤鱼&qu ...

  10. ReportView 添加自动增长序号

    在显示序号的列中输入相关的值: 在此表达式的后面是Nothing,不是null,不要搞错.