码迷,mamicode.com
首页 > 其他好文 > 详细

【数论干货】线性方法求阶乘,逆元和组合数

时间:2019-04-10 18:01:37      阅读:598      评论:0      收藏:0      [点我收藏+]

标签:turn   线性   证明   return   否则   \n   while   根据   组合   

线性求法,即预处理出阶乘以及逆元

阶乘的递推式非常好想,fac[i]=fac[i-1]*i

    fac[0]=1;
    for(register int i=1;i<=maxn;++i)
        fac[i]=(1ll*fac[i-1]*i)%mod;

至于逆元,易证inv[i]=inv[i+1]*(i+1)

    inv[maxn]=qpow(fac[n+m],mod-2);
    for(register int i=maxn-1;i>=0;--i)
        inv[i]=(1ll*inv[i+1]*(i+1))%mod;

不过最大的逆元需要使用快速幂处理一下,就像这样

ll qpow(ll x,ll n) //x的n次方
{
    ll res=1;
    while(n)
    {
        if(n&1) res=(1ll*res*x)%mod;
        x=(1ll*x*x)%mod;
        n>>=1;
    }
    return res;
}

于是根据数学公式,组合数就非常好求了

ll C(ll n,ll m)
{
    ll res=(1ll*fac[n]*inv[m])%mod;
    return (1ll*res*inv[n-m])%mod;
}

需要注意,最好将式子拆成两部分,否则容易乘爆
(连WA8次的惨痛教训)

最后我们就可以愉快地输出了

printf("%lld\n",C(n,m));

数学证明我会写在以后的博客中

【数论干货】线性方法求阶乘,逆元和组合数

标签:turn   线性   证明   return   否则   \n   while   根据   组合   

原文地址:https://www.cnblogs.com/tqr06/p/10684917.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!