组合数学总结

  • 组合数学

  • 公式

  

  

  

  

  

  (二项式定理)

  • O(n)预处理,O(1)求组合数预处理阶乘fac数组。

  预处理fac数组,需取模,则需处理出ifac(阶乘逆元)。

  code:

        fac[0]=1;
        for(int i=1;i<N;i++) fac[i]=fac[i-1]*i%p;
        ifac[N-1]=power(fac[N-1],mod-2);
        for(int i=N-2;~i;i--) ifac[i]=ifac[i+1]*i+1;

  然后用套公式即可。

  • Lucas定理

  核心:

  

  Lucas定理用于求一些n,m很大,但是p比较小的组合数直接记公式即可。

  code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=1e5+10;
int T;
LL fac[N];
LL n,m,p;

LL qpow(LL a,LL b)
{
    LL res=1;
    a%=p;
    while(b)
    {
        if(b&1)res=a*res%p;
        a=a*a%p;b>>=1;
    }return res%p;
}

LL C(LL n,LL m)
{
    if(n<m)return 0;
    return fac[n]%p*qpow(fac[m],p-2)%p*qpow(fac[n-m],p-2)%p;
}

LL Lucas(LL n,LL m)
{
    if(m==0)return 1;
    return Lucas(n/p,m/p)%p*C(n%p,m%p)%p;
}

int main()
{
    scanf("%d",&T);
    fac[0]=1;
    while(T--)
    {
        scanf("%lld%lld%lld",&n,&m,&p);
        for(int i=1;i<=p;i++)fac[i]=(fac[i-1]*i)%p;
        printf("%lld\n",Lucas(n+m,m));
    }
}

 

   

 

posted @ 2019-07-23 19:43  EPs1l0h  阅读(264)  评论(0编辑  收藏  举报