zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp
    默默的等式
    P3403 跳楼机
    作物
    【bzoj3174】[Tjoi2013]拯救小矮人
    【bzoj4976】宝石镶嵌
    BZOJ2121-字符串游戏
    mzf的考验
    牛客网round1
    jloi2015
  • 原文地址:https://www.cnblogs.com/allthestars/p/9904103.html
Copyright © 2011-2022 走看看