组合数取模

关于公式 C(n,m)=n!/m!(n-m)!  中带有除法,我们可以不能直接将n!和m!和(n-m)!直接取模再相除

所以这里需要求逆元,我们先预处理出每一个阶乘的逆元,然后再代入公式得:

C(n,m)=n!*ni(m)*ni(n-m) %mod   ni[i]为i的逆元

求逆元可以用费马小定理,也可以用扩展欧几里得,扩展欧几里得可以参考这篇博客,费马小定理在该博客将给出结论

费马小定理:

假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p),即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。

显然 ni(a)=a^(p-2)

 1 ll qm(ll x,ll k){   //快速幂
 2     if(k==0)return 1;
 3     ll sum=1;
 4     while(k){
 5         if(k&1)sum*=x,sum%=mod;
 6         k>>=1;x*=x;
 7         x%=mod;
 8     }
 9     return sum;
10 }
11 ll ni[N],f[N]; //fi为i的阶乘
12 void prework(){
13     f[0]=1;ni[0]=qm(f[0],mod-2);
14     for(int i=1;i<=n;i++){
15         f[i]=f[i-1]*i;f[i]%=mod;
16         ni[i]=qm(f[i],mod-2);
17     }
18 }

预处理出逆元那么就可以用上述公式O(1)求得组合数C(n,m)了

1 ll query(int n,int m){
2     ll ret=((f[n]*ni[m]%mod)*(ni[n-m]))%mod;
3     return ret;
4 }
原文地址:https://www.cnblogs.com/Yuzao/p/7341765.html