数论干货线性方法求阶乘,逆元和组合数
Posted tqr06
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论干货线性方法求阶乘,逆元和组合数相关的知识,希望对你有一定的参考价值。
线性求法,即预处理出阶乘以及逆元
阶乘的递推式非常好想,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
",C(n,m));
数学证明我会写在以后的博客中
以上是关于数论干货线性方法求阶乘,逆元和组合数的主要内容,如果未能解决你的问题,请参考以下文章