lucas定理(hdu3037,)

这几天脑袋秀逗了,想什么都想不出来,上课状态也特别差,老是犯困,看来最近状态不是一般的差,以后不熬夜了,注意作息,调整状态好好学习了。用心看了下lucas定理,就整理下来吧。

Lucas定理


定义:

A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0])modp同余

即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p) 

怎么用:

Lucas定理是用来求 C(n,m) mod p,p为素数的值(注意:p一定是素数)

有人会想,C(n,m)不能用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式来递推吗?

( 提示:C(n, m) mod p = n!/(m!(n - m)!) mod p )

可以是可以。但当n,m,p都很大时,你递推所用的时间就会很爆炸了。所以,这就需要用到Lucas定理来解决了。

因此,Lucas定理用来解决大组合数求模是很有用的

心得:当你求解大的组合数,递推特别耗时的时候,并且让你对一个素数取模的时候,那一定就是lucas定理了。

注意:

Lucas定理最大的数据处理能力是p在10^5左右。

表达式:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p。(可以递归)

递归方程:(C(n%p, m%p)*Lucas(n/p, m/p))%p。(递归出口为m==0,return 1)

已知C(n, m) mod p = n!/(m!(n - m)!) mod p。显然是除法取模,这里又要用到m!(n-m)!的逆元。
求逆元
根据费马小定理

已知(a, p) = 1,则 ap-1 ≡ 1 (mod p),  所以 a*ap-2 ≡ 1 (mod p)。

也就是 (m!(n-m)!)的逆元为 (m!(n-m)!)p-2 。






以上就是卢卡斯定理的内容了

下面是模板代码,模板求得是C(m+n,m),题目出处http://acm.hdu.edu.cn/showproblem.php?pid=3037

代码:

#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
const int mo=1e6+10;
ll fact[mo];
ll n,m,p;
void init()//对阶乘进行预处理
{
    fact[0]=1;
    for(int i=1;i<=p;i++)
        fact[i]=fact[i-1]*i%p;
}
ll quickmod(ll a,ll b)//快速幂
{
    ll ans=1;
    ll temp=a%p;//不太明白,需要请教
    while(b){
        if(b&1) ans=ans*temp%p;
        temp=temp*temp%p;
        b>>=1;
    }
    return ans;
}

ll comb(ll n,ll m)//comb用来求解组合数
{
    if(m>n) return 0;
    return fact[n]*quickmod(fact[m]*fact[n-m],p-2)%p;//根据费马小定理求逆元因为a^(p-1)modp==1所以a^(p-2)modp就是a的逆元
}

ll lucas(ll n,ll m)//卢卡斯定理
{
    if(m==0) return 1;//出口
    else return  (comb(n%p,m%p)*lucas(n/p,m/p))%p;//卢卡斯定理
}
int main()
{
    ll t;scanf("%lld",&t);while(t--){
        scanf("%lld%lld%lld",&n,&m,&p);
        init();
        printf("%lld\n",lucas(n+m,m));
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值