常用线性打表求逆元方式

常用线性打表求逆元方式

一、 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

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值