浅谈 Lucas 定理

Lucas 定理是用来求 Cmnmodp 的。

定理

CmnCmmodpnmodpCm/pn/p(modp)

证明略

应用

开头不就说了是求组合数的嘛awa

因为卢卡斯定理可以把一个巨大的组合数给拆掉,所以利用这个性质就能够求出 Cmnmodp,也就是说:

CmnCm0n0Cm1pn1pCm2p2n2p2(modp)

Cmni=0Cmipinipi(modp)

可快速幂,把 mn 拆成 p 进制数,然后直接暴力。

比如模板题 P3807

#include<iostream>
using namespace std;
const int N=100010;  //最大值
typedef long long ll;
ll a[N];
int p;
inline ll qpow(ll n,int k) //快速幂用来求逆元
{
    ll ans=1,base=n;
    while (k)
	{
        if(k&1) ans=ans*base%p;
        base=base*base%p;k>>=1;
    }
    return ans%p;
}
inline ll C(ll m,ll n)  //组合数,有除法用逆元
{
    if (m<n) return 0;
    if (m==n||!n) return 1;
    if (n==1) return m;
    return a[m]*qpow(a[n],p-2)%p*qpow(a[m-n],p-2)%p;
}

inline ll Lucas(ll m,ll n)  //Lucas 代入公式
{
    if (!n) return 1;
    return C(m%p,n%p)*Lucas(m/p,n/p)%p;
}
int main()
{
    int t;
    cin>>t;
    while (t--)  //多组数据
	{
        ll m,n;
        cin>>n>>m>>p;
        a[0]=1;
        for (int i=1;i<=p;i++) a[i]=(a[i-1]*i)%p;  //预处理阶乘用来求组合数
        cout<<Lucas(n+m,m)<<'\n';
    }
    return 0;
}
posted @   yspm  阅读(190)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示