MITE:组合数

6 篇文章 0 订阅

想比大家对组合数都十分了解了

在这里插入图片描述

下文我们都直接用C(n,m)来表示了

正常组合数

杨辉三角

在学习组合数的时候,老师肯定会讲杨辉三角的,所以这里也不多累赘了。

杨辉

int comb[N][N];
void init()
{
	for(int i=0;i<N;i++;i++)
	{
		comb[i][0]=comb[i][i]=1;
		for(int j=1;j<;j++)
			comb[i][j]=comb[i-1][j]+comb[i-1][j-1];
	}
}

代码只是简单的打表而已。复杂度O(n^2)

直接求法

毕竟是有直接的数学公式的,C(n,m)=n!/m!/(n-m)!

所以只要打表出每一个数的阶乘,然后遍历一遍暴力求就行,复杂度O(n)

但是总所周知怎么又是众所周知 ,阶乘是很大的,比如20!= 2432902008176640000

所以一般来说要用逆元来求,一般这种题是要求取模的,所以用两个数组一个存阶乘的逆元一个存阶乘就行了

但如果题目没取模怎么办,问题不大,自己取一个比较大的质数当模数就好了。

int F[N],Finv[N],inv[N];
//inverse element : 逆元
//factorial :阶乘
//Finv 阶乘的逆元
void init()
{
	inv[1] = 1;
	for(int i=2;i<N;i++)
		inv[i]=(mod-mod/i)*1ll*inv[mod%i]%mod;
	F[0]=Finv[0]=1;
	for(int i = 1;i<N;i++)
	{
		F[i]=F[i-1]*1ll*i%mod;
		Finv[i] = Finv[i-1]*1ll*inv[i]%mod:
	}
}
//C(n,m)
int comb(int n,int m)
{
	if(m<0 || m>n)return 0;
	return F[n]*1ll*Finv[n-m]%mod*Finv[m]%mod;
}

但其实这其实是别人博客里的代码,这里安利一下这个大佬的博客,也是一个数论的专题,我觉得写的很好。
镜外之主

如果觉得我写的不好的话可以看这个大佬的博客哇(然后大家都不来看我的了,嘤嘤嘤)

大组合数–Lucas定理

Lucas定理就一行公式

C(n, m) % p = C(n / p, m / p) * C(n%p, m%p) % p

这就可以处理n和m都很大但p1比较合理的情况下的组合数了。

ll lucas(ll n,ll m,ll p)
{
	return m?lucas(n/p,m/p,p)*comb(n%p,m%p,p)%p:1;
}

原理的话在写了,真的再写了,咕是不可能咕,在路上了咕

CRT(论p不是素数怎么办)

咕咕咕


  1. 注意,p得是质数 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值