逆元法求组合数

B - The Circumference of the Circle (求三角形外接圆)

(a+b)%p = a%p + b%p ;
(a-b)%p = a%p - b%p ;
(a*b)%p = a%p * b%p ;
但是( a b \frac{a}{b} ba)%p ≠ a m o d p b m o d p \frac{a mod p}{b mod p} bmodpamodp这种时候就要用到逆元
在求组合数时 C ( n m ) \tbinom{n}{m} (mn) = n ! m ! ∗ ( n − m ) ! \frac{n!}{m!*(n-m)!} m!(nm)!n! %p ≠ n ! m o d p m ! ∗ ( n − m ) ! m o d p \frac{n! mod p}{m!*(n-m)! mod p} m!(nm)!modpn!modp , 求逆元的时候用到费小马定律

费小马定律

若a 与 p互质且p为质数时 ,a(p-1)%p== 1%p ;

因为ap-1 = ap-2 * a , 所以ap-2 为a 的逆元 ,即( x a \frac{x}{a} ax)%p=(x%p)*(ap-2%p)%p ;

求C ( n m ) \tbinom{n}{m} (mn)%p
  1. 求出所有小于n的阶乘用f[i] 表示(f[i]%p)
  2. 求m! 的逆元即f[m] 的逆元 a = fastpow(f[m],p-2) (快速幂取模)
  3. 求(n-m)! 的逆元 b = fastpow(f[n-m],p-2)
  4. C ( n m ) \tbinom{n}{m} (mn)%p = f[n] * a * b ;

模板:

#include <iostream>
using namespace std ; 
typedef long long ll ; 
const int N=1e5+5 ; 
const int mod = 998244353 ;
int f[N] ; 
ll n , k , p ;
ll fastpow(ll a , ll b){
	ll res = 1 ; 
	while(b){
		if(b&1)	res=res*a%mod ; 
		a = a*a%mod ; 
		b >>= 1 ; 
	}
	return res ;
} 
int main(){
	cin >>n>>k>>p ;
	f[0] = f[1] = 1 ; //f[0] 也要赋值为 1 
	for(ll i=2;i<=n;++i)	f[i] = f[i-1]*i%mod ; 
	ll ans = 0 , q = (mod+1-p)%mod ;
	for(ll i=k;i<=n;++i){
		ll c = f[n]*fastpow(f[i],mod-2)%mod*fastpow(f[n-i],mod-2)%mod ;//逆元法求组合数 
		ll d = fastpow(p,i)*fastpow(q,n-i)%mod ; //当前概率 
		ans = (ans+c*d%mod)%mod ; //求和 
	}
	cout << ans << endl ;
	return 0 ; 
}

参考及详细解说—> 逆元求组合数
还有一个其他方法求组合数的 —> 求组合数的各种方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值