组合数学,像数论一样是发源自数学的恶心东西,在计算机上更是与取余成为结发夫妻,与DP和数论的关系也不一般。更因为计算机令人惊骇的枚举耐心,出现了更加可怕的变种题目。好了,现在进入正题。
1.计数原理(我不愿多说了)
1)加法原理 2)乘法原理 3)抽屉原理 4)容斥原理
尴尬事实:
加法原理和乘法原理——基本不会单考...
抽屉最多是你在草稿纸里的证明步骤...
容斥可以单独考但大多还是会和素数、DP或组合数一起考,让人恶心...
2.组合数(总是要打表...)
1)阶乘法:
根据组合数公式:C(n,m)=n!/m!/(n-m)!,在需要组合数不多(例如只求一个)且精度在整形、长整形或无符号长整形中可以存下这个阶乘便可以使用,可以先将大于n/2的m转换一下就可以较快求出了。有时除法又可以结合逆元(只不过不太好用就是了,老是不互质就很尴尬了)(O(n):1+空间1)
2)杨辉三角法:
根据组合数公式:C(n,m)=C(n-1,m)+C(n-1,m-1),可以很轻松地求出一大批组合数,只要n、m不会太大就可以很方便地求出来,一次性求出很多组合数,但有些占用内存,而且如果组合数用的不多会很亏。不过还是最常用的方法,因为杨辉三角只涉及到加法,取余很容易,不需很麻烦。(O(n^2):n^2+空间n^2)
3)Lucas定理法:
根据组合数公式:C(n,m)%p(p为质数)=C(n/p,m/p)*C(n%p,m%p)%p ,可以快速求出组合数取余并不用担心溢出,但只适用于p很小并且n、m大于p时,例如n、m上限为1e9,p上限为1e5之类。但通常需要配合阶乘法或杨辉三角法求出小一些的组合数,较为复杂。预处理:O(p^2)+求值:O(log(n,p)):1+空间:p^2
4)特殊情况:
有时候组合数和数论一起考的话,可以用分解质因数后质因子的次数来表示这一个组合数,用来判断倍数很有效
3.组合数学DP
如果你还不知道这是什么,请点击湫秋系列故事——安排座位,然后就会理解这种题的恶心之处了。组合数学DP像这种需要很牛的思维,计算方案一定要不重不漏,例如这道题所有方案都要考虑,不能以为只有插在正常序列才是合法的,有可能刚好插在不合法孔中反而让它变成了合法序列都是要考虑的。还有A Famous Stone Collector也是如此。但也不多说了,还是看看下面的经典组合问题吧!
4.盒子与小球
接受盒盒与球球的制裁吧!
1)给你k个小球放入n个盒子,小球全都相同,盒子全都不同,盒子可为空,求方案总数,难度系数★★☆
考虑如下方程,解的个数即为答案
X1+X2+X3+...+Xn=k(Xi∈N)
将所有X加上1变成Y,答案不变
Y1+Y2+Y3+...+Yn=k+n(Yi∈N*)
由于考虑顺序,所以就类似于某个经典问题——小球挡板,用挡板法可得解为
C(k+n-1,n-1)
2)给你k个小球放入n个盒子,小球全都不同,盒子全都相同,盒子可为空,求方案总数,难度系数★★★
裸的斯特林数还用说什么(当然要说不那么裸就将盒子里先垫上几个虚假的球使盒子不能为空)
S(k+n,n)
3)给你k个小球放入n个盒子,小球全都不同,盒子全都不同,盒子可为空,求方案总数,难度系数★★★★
其实在第2问后就显得很简单了,只需要把盒子随机乱排即可
S(k+n,n)*n!
4)给你k个小球放入n个盒子,小球全都相同,盒子全都相同,盒子可为空,求方案总数,难度系数★★★★★
整数的分解型题,DP解
P(i,j)表示i个球放入j个盒子方案数
P(i,j)=sum(P(i-j,k))(1<=k<=j)
P(1,1)=1
然后一样的将盒子全都垫上一个球
解为
P(k+n,n)
5.注意事项
1)精度
通常关于组合数学的题都会出现极大的答案,所以通常会模一个数,而在模之前(非常)有可能会出现乘法溢出,所以要实现估计好使用的精度,是用int(其实基本上都会爆)、long long(还好,但也必须步步模)还是unsigned long long(其实也很少用)必须要准。
2)内存
像是杨辉三角之类的表什么的很容易爆掉内存,必须在使用时尽量不触犯内存上限,例如可以C(n,n/2-k)就不要C(n,n/2+k)什么的。
3)除法
要知道取余最忌讳除法了,不然就只能用逆元很让人伤脑筋。不是因为逆元难求,而是因为求逆元有可能根本就没有逆元,即便是对素数的逆元,也不见得就有(可能这个数本身是被取余数的倍数)。要谨慎使用逆元!