组合数取模(sdut3895+HDU3037)逆元法或Lucas

组合数取模有三种方法
第一种是杨辉三角用数组跑,时间复杂度高
第二种使用逆元法求,适用于m,n较小,而mod较大的情况
第三种是Lucas定理适用于n,m较大的情况;

逆元法
记需要取余的数mod为p

##p要求是质数,不然就GG吧

虽 然 有 C n m = n ! m ! ( n − m ) ! , 但 由 于 取 模 的 性 质 对 于 除 法 不 适 用 虽然有C_n^m=\frac{n!}{m!(n−m)!},但由于取模的性质对于除法不适用 Cnm=m!(nm)!n! 所 以 C n m % p ≠ ( n ! % p m ! % p ( n − m ) ! % p ) % p 所以C_n^m\%p\neq\left(\frac{n!\%p}{m!\%p(n−m)!\%p}\right)\%p Cnm%p=(m!%p(nm)!%pn!%p)%p
所以需要把“除法”转换成“乘法”,才能借助取模的性质在不爆long long的情况下计算组合数。这时候就需要用到“逆元”!

逆元:对于a和p,若a*b%p≡1,则称b为a%p的逆元。

对 于 ( a b ) % p , 假 设 c 为 b 的 逆 元 , 即 b ∗ c % p ≡ 1 , 那 么 ( a b ) % p = ( a ∗ b ∗ c % p b ) 对于\left({a}\over{b}\right)\%p,假设c为b的逆元 ,即b*c\%p\equiv1,那么\left({a}\over{b}\right)\%p=\left({a*b*c\%p}\over{b}\right) (ba)%p,cb,bc%p1,(ba)%p=(babc%p)
即 ( a b ) % p = ( a ∗ c % p ) = ( ( a % p ) ∗ c % p ) % p 即\left({a}\over{b}\right)\%p=\left(a*c\%p\right) =\left(\left(a\%p\right)*c\%p\right)\%p (ba)%p=(ac%p)=((a%p)c%p)%p

逆元的求法有三种,一种是扩展欧几里得求逆元,转换成同余方程,一种是线性求逆元,另一种就是当p是质数时强大的费马小定理;

###扩展欧几里得
a与b互质,存在n,m使方程am+bn=gcd(a,b)=1成立
a*m%b+0=1成立
m就是a%b的逆元.
求逆元代码:

long long inv(long long a,long long p)
{
	long long x,y;
	long long d=extend_gcd(a,p,x,y);
	if(d==1) return (x%n+n)%n; 
	else return -1;
}
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
	if(a==0&&b==0)return -1;
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	long long d=extend_gcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}

###线性求逆元

//a<p
long long inv(long long a,long long p)
{
	if(a==1)
		return 1;
	return inv(p%a,p)*(p-p/a)%p
}

###费马小定理:

对 于 质 数 a , a p − 1 % p ≡ 1 , 又 因 为 a p − 1 = a p − 2 ∗ a , 所 以 a p − 2 是 a 的 逆 元 , 那 样 就 可 以 用 快 速 幂 求 逆 元 了 对于质数a,a^{p-1}\%p\equiv1,又因为a^{p-1}=a^{p-2}*a,所以a^{p-2}是a的逆元,那样就可以用快速幂求逆元了 a,ap1%p1,ap1=ap2a,ap2a,
对 于 组 合 数 n ! m ! ( n − m ) ! % p = ( n ! m ! % p ∗ 1 ( n − m ) ! % p ) % p 对于组合数\frac{n!}{m!(n−m)!}\%p=\left(\frac{n!}{m!}\%p*\frac{1}{\left(n-m\right)!}\%p\right)\%p m!(nm)!n!%p=(m!n!%p(nm)!1%p)%p

首 先 用 费 马 小 定 理 求 m ! 的 逆 元 记 作 m 逆 元 = ( m ! ) p − 2 , 首先用费马小定理求m!的逆元记作m_{逆元}=\left({m!}\right)^{p-2}, m!m=(m!)p2, 然 后 求 出 ( n − m ) ! 的 逆 元 记 作 n m 逆 元 = ( ( n − m ) ! ) p − 2 然后求出(n-m)!的逆元记作nm_{逆元}=\left({(n-m)!}\right)^{p-2} (nm)!nm=((nm)!)p2 C n m % p = n ! m ! ( n − m ) ! % p = ( n ! m ! % p ∗ 1 ( n − m ) ! % p ) % p = ( ( n ! % p ∗ m 逆 元 % p ) % p ∗ ( 1 ∗ n m 逆 元 % p ) % p ) % p C_n^m\%p=\frac{n!}{m!(n−m)!}\%p=\left(\frac{n!}{m!}\%p*\frac{1}{\left(n-m\right)!}\%p\right)\%p=\left(\left(n!\%p*m_{逆元}\%p\right)\%p*\left(1*nm_{逆元}\%p\right)\%p\right)\%p Cnm%p=m!(nm)!n!%p=(m!n!%p(nm)!1%p)%p=((n!%pm%p)%p(1nm%p)%p)%p

sdut3895(2017山东省赛C题)就是逆元求组合数的题目,不能用卢卡斯定理,TLE,TLE,TLE…
SDUT3895题目链接
2017山东省赛C题题解

###Lucas定理(大部分情况 p< 1 0 5 10^5 105)证明过程看这里
C n m % p = ( C n % p m % p % p ∗ C n / p m / p % p ) % p C_n^m\%p=\left(C_{n\%p}^{m\%p}\%p*C_{n/p}^{m/p}\%p\right)\%p Cnm%p=(Cn%pm%p%pCn/pm/p%p)%p 且 C n 0 = 1 ; 且C_n^0=1; Cn0=1;
这样我们就可以用逆元法求出 C n % p m % p C_{n\%p}^{m\%p} Cn%pm%p,然后递归求解 C n m % p C_n^m\%p Cnm%p
Lucas定理模板(C(m,n)代表 C n m C_n^m Cnm)

long long Lucas(long long n,long long m)  
{  
    if(m==0)  
        return 1;  
    return Lucas(n/p,m/p)*C(n%p,m%p)%p;  
}  
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值