组合数学<1>——组合数学基础

今天我们聊聊组合数学。(本期是给刚刚学习组合数学的同学看的,dalao们可以自行忽略)

建议:不会求逆元的出门左转数论<2>,不会数论的出门右转数论<1>

加乘原理

加乘原理小学奥数就有。

总的来说:加法原理:分类;乘法原理:分步

比如说,我问你有3条裤子2件衣服,只买一个,有几种可能性?3+2对吧。

那还是3条裤子2件衣服,每个买一个,有几种?3*2对吧。

排列组合

排列组合也是小学奥数的东西。

举个栗子,n个学生,选m个出来排队,有几种方案?A(n,m)

稍微解释一下A(n,m)=n\times (n-1)\times (n-2)\times (n-m+1)......=\frac{n!}{(n-m)!}

那还是刚刚的问题,但是不考虑排队的顺序,有几种方案?C(n,m)

由于不考虑方案,所以要在A(n,m)的基础上除m!,也就是C(n,m)=\frac{n!}{m!(n-m)!}

圆排列

有N个人围成一个圈,圈可以顺时针旋转,问有多少种方案?

其实很简单。不考虑圈是n!,考虑了是(n-1)!,也就是除掉一个N。

隔板法

原型:x_1+x_2+......+x_n=m\: (x_i>1),问有多少种方案。

x_i旁边放隔板,有n-1个隔板,所以答案是C(m-1,n-1)

变形1:x_1+x_2+......+x_n=mx_i可以是0,问方案数。

把每个x_i加1,也就是(x_1+1)+(x_2+1)+......+(x_n+1)=m+n\: (x_i\geq 1)

答案是C(m+n-1,n-1)

变形2:1\leq x_1< x_2 <...... <x_n\leq m,求方案数。

(x_1-1+1)+(x_2-x_1)+......(x_n-x_{n-1}+1)=m+1,答案为C(m,n)!!!

变形3:A_1\times A_2\times A_3\times ......A_N=M,求方案数。

我们知道,M=p_1^{\alpha_1}+p_2^{\alpha_2}+......+p_k^{\alpha_k},而每个A_i的分解质因数都在M里,就得到

\beta_{1,1}+\beta_{1,2}+......+\beta_{1,N}=\alpha_1,然后就转化为原型。(\beta是每个数的指数)

-----------------------------------------↑数学-------↓实现-----------------------------------------

求组合数

首先可以想到的是根据定义操作。

int C(int n,int m){
	int res=1;
	for(int i=m-n+1;i<=m;i++)
		res=res*i/(i-m+n);
	return res;
}

我这里稍微优化了一下,边乘边除,防止溢出。

取模组合数

有的题ans太大了,需要大家取模。但是在数论<2>中我们说过,这除法有鬼啊,模不了,不能只

接求,那怎么办呢?

杨辉三角递推

观察杨辉三角,你会发现,杨辉三角的(i,j)就是C(i,j)的值。(竖过来看)

而且,还满足C(i,j)=C(i-1,j-1)+C(i-1,j),因此就可以\Theta (n^2)求组合数了。

而且这是加法,很好模。当然,它只适用于nm较小的情况。

逆元

或许大家有疑问,我们能不能搞个前缀积,然后C(n,m)=prod(n)/prod(m)/prod(n-m)

还搞什么杨辉三角呢?有道理,但是我们知道,除法并不支持模运算(⊙︿⊙)

所以,我们可以用逆元。逆元怎么求在数论<2>中说过,这里不再赘述。

然后,根据上面的式子就可以求逆元啦!

long long factorial[maxn],invf[maxn];
long long exgcd(long long a,long long b,long long &x,long long &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	long long res=exgcd(b,a%b,x,y);
	long long tmp=x;
	x=y;
	y=tmp-a/b*y;
	return res;
}
long long inverse(long long n,long long mod){
	long long x,y;
	long long _=exgcd(n,mod,x,y);
	x%=mod;
	if(x<0)
		x+=mod;
	return x;
}
void precompute(){
	factorial[0]=1;
	for(int i=1;i<=maxn;i++)
		factorial[i]=factorial[i-1]*i%P;
	invf[maxn]=inverse(factorial[maxn],P);
	for(int i=maxn-1;i>=0;i--)
		invf[i]=invf[i+1]*(i+1)%P;
}
long long C(int n,int m){
	long long res=factorial[n];
	res=res*invf[n-m]%P;
	res=res*invf[m]%P;
	return res;
}

都开了long long,因为组合数学题的范围一般很大。

例题

CF630F:

很easy,C(n,5)+C(n,6)+C(n,7)就搞定了。边乘边除即可。

CF1081C:

有n块砖,切k刀,即C(n-1,k),由于颜色不确定,要再乘上(m-1)^k

由于nk较小,用杨辉三角求组合数即可。

CF630I:

很简单。答案是:4 \times 2\times 3\times 4^{n-3}+(n-3)\times 9\times 4^{n-4}

CF1433E:

圆排列板题。答案是2\frac{(n-1)!}{n}

CF1236B:

答案是n^{2^m-1}

CF57C:

就是隔板法。参考变式2

ok,以上就是本期的全部内容了,我们下期再见!_(:з」∠)_

小贴士:大部分组合数学题目不是板题,大家应该灵活一些,先分类,再分步,定序去重。

当然,你也可以每道题都用高精度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值