组合数取模

组合数取模——————卢卡斯定理
 
//组合数取模——————卢卡斯定理
//扩展欧几里得求逆元
int exgcd(int a,int b,int &x,int &y)//扩展欧几里得
{
    if(b==0)
    {
        x=1;y=0;return a;
    }
    else
    {
        int gcd=exgcd(b,a%b,x,y);//gcd=exgcd(b,a%b,y,x);  y-=(a/b)*x;
        int t=x;
        x=y;
        y=t-(a/b)*y;
    }
    return gcd;
}
int niyuan(int a,int mod)//求逆元
{
    int x,y;
    exgcd(a,mod,x,y);
    return (x%mod+mod)%mod;
}

//费马小定理求逆元
void get_fac()//阶乘打表
{
    fac[0]=fac[1]=1;
    for(int i=2;i<N;i++)
        fac[i]=fac[i-1]*i;
}
int quick_pow(int a,int b,int mod)//快速幂a^b%mod
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
int niyuan(int a,int b)
{
    return quick_pow(a,b-2,b);
}

int C(int n,int m,)//计算c(n,m)
{
    return fac[n]*niyuan(fac[m],mod)%mod*niyuan(fac[n-m],mod)%mod;
}
//Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)
int lacus(int n,int k)
{
    if(k==0)return 1;
    else
        return C(n%mod,m%mod)*lacus(n/mod,m/mod)%mod;
}

对于较小的组合数,可直接递归求组合数

int comb(int x,int y)
{
    c[0][0]=c[1][1]=c[1][0]=1;
    for(int i=2;i<maxn;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=i;j++)
            c[i][j]=c[i-1][j]%mod+c[i-1][j-1]%mod;
    }
    return c[x][y];
}

 

posted @ 2018-07-31 11:43  蓝猫爱宇宙  阅读(104)  评论(0编辑  收藏  举报