常用线性打表求逆元方式
一、 1 ~ n 的逆元
递推公式:
inv[i] = ( p - p / i ) * inv[p % i] % p
代码模板:
inv[1]=1;
for (i = 2;i <= N;i++)
{
inv[i] = ((mod - mod/i) * inv[mod%i] ) % mod;
}
证明过程:
二、n! 的逆元
递推公式:
inv[i] = inv[i + 1] * (i + 1) % MOD
代码模板:
//先利用费马小定理求出 n! 的逆元,再倒推求(n-1)!... 的逆元
inv[N] = power(fac[N], MOD - 2); //fac[n]为 N 的阶乘
for (i = N - 1; i >= 0; i--)
inv[i] = 1ll * inv[i + 1] * (i + 1) % MOD;
证明过程:
应用:求组合数
原理:
C(n,m) = [ n! / (m! * (n-m)! ) ] % mod
= n! % mod * ([m!]^-1 ) * ( [(n-m)!]^-1) % mod
const int N = 2e6+5;
const int mod = 20100403;
int jc[N]; //阶乘表
int inv[N]; // N! 的逆元!! 注意
int n,m;
int power(int a,int n){
int ans = 1;
while(n){
if(n&1) ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
n >>= 1;
}
return ans;
}
int C(int n,int m){
int z = 1ll * jc[n] * inv[m] % mod;
return 1ll * z * inv[n-m] % mod;
}
int main(){
scanf("%d%d",&n,&m);
jc[0] = 1;
for(int i = 1;i < N;++i) jc[i] = 1ll * jc[i-1] * i % mod;
inv[N-1] = power(jc[N-1],mod-2);
for(int i = N-2;i >= 0;--i) inv[i] = (1ll * inv[i+1] * (i+1)) % mod;
// cout<<C(n+m,n)<<endl;
// cout<<C(n+m,n-1)<<endl;
// 卡特兰数
printf("%d\n",(C(n+m,m) - C(n+m,m-1) + mod) % mod);
return 0;
}
参考链接:
https://www.luogu.com.cn/blog/user49618/solution-p3811
https://www.luogu.com.cn/blog/user49618/solution-p3811
求逆元的三种方法方法:
https://www.cnblogs.com/wsy107316/p/11520602.html