Lucas定理

P3807 【模板】卢卡斯定理

Lucas定理是用于处理组合数取模的定理

通常用于解决阶乘无法解决的问题(计算很大的组合数时要用到卢卡斯定理(Lucas)防止爆longlong);

定理:Lucas(n,m,p)=c(n%p,m%p)×Lucas(n/p,m/p,p)

证明:lucas定理证明 我就不写了

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    int x=0,o=1;char ch=getchar();
    while(!isdigit(ch)&&ch!='-') ch=getchar();
    if(ch=='-') o=-1,ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int MAXN=100000;
int n,m,t,p,c[MAXN+10],y[MAXN+10],b[16],ans;
inline int qpow(int x,int y)//快速幂,不解释
{
    if(y==0) return 1;
    int temp=qpow(x,y/2);
    if(y%2==0) temp=temp*temp%p;
    else temp=temp*temp*x%p;
    return temp;
}
inline int C(int N,int M)//求组合数
{
    if(M>N) return 0;
    return 1ll*c[N]%p*qpow(c[M],p-2)*qpow(c[N-M],p-2)%p;//1/n!与n!互为逆元,用费马小定理求出1/n!就是qpow(c[n],p-2);
}
inline int lucas(int n,int m)//lucas定理
{
    if(m==0) return 1;
    return (long long)C(n%p,m%p)*lucas(n/p,m/p)%p;
}
signed main()
{
    t=read();
    while(t--)
    {
        n=read(),m=read(),p=read();
        c[0]=1;
        for(long long i=1;i<=p;i++) c[i]=c[i-1]*i%p;//c[i]为i的阶乘
        ans=lucas(n+m,m);
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/allthestars/p/9904103.html