十四、 组合数学

人们在生活中经常会遇到排列组合问题。比如说:在555个礼物中选222个,问有多少种选取方法?
组合数学就是研究一个集合内满足一定规则的排列问题。这类问题如下:

  1. 存在问题:即判断这些排列是否存在
  2. 计数问题:计算出有多少种排列,并构造出来
  3. 优化问题:如果有最优解,给出最优解
    组合数学涉及的内容很多,包括:
  4. 基本计数规则:乘法规则、加法规则、生成排列组合、多项式系数、鸽巢原理等。
  5. 计数问题:二项式定理、递推关系、容斥定理、Polya定理等。
  6. 存在问题:编码、组合设计、图论中的存在问题等。
  7. 组合优化:如匹配和覆盖、图和网络的优化问题。
    这部分之讲解一些简单的类型。
鸽巢原理(抽屉原理)

内容非常简单:把n+1n+1n+1个物体放进nnn个盒子,至少有一个盒子包含两个或更多的物体。
例如:在150015001500人中,至少有555人生日相同;nnn个人互相握手,一定有两个人握手的次数相同。

比如说:小A有KKK种糖果,每种数量已知,小A不喜欢连续两次吃同样的糖果,问有没有可行的吃糖方案。
该题是非常典型的鸽巢原理问题,可以用“隔板法”求解。找出最多的一种糖果,把它的数量NNN看成NNN个隔板,隔成NNN个空间(把每个隔板的右边看成一个空间);其他所有糖果的数量为SSS

  1. 如果S<N−1S<N-1S<N1,把SSS个糖果放到隔板之间,这NNN个隔板不够放,必然至少有两个隔板之间没有糖果,由于这两个隔板是同一种糖果,所以无解。
  2. S≥N−1S≥N-1SN1时,肯定有解。其中一个解是把SSS个糖果排成一个长队,注意同种类的糖果是挨在一起的,然后每次取NNN个糖果,按顺序一个一个地放进NNN个空间。由于隔板的数量比每一种糖果的数量都多,所以不可能有两个同样的糖果被放进一个空间里。把SSS个糖果放完,就是一个解,一些隔板里面可能放几种糖果。
杨辉三角和二项式定理

读者一定非常熟悉排列和组合公式。
排列:Ank=n!(n−k)!A^k_n=\displaystyle \frac{n!}{(n-k)!}Ank=(nk)!n!
组合:Cnk=(nk)=Ankk!=n!k!(n−k)!C^k_n=\begin{pmatrix}n\\k \end{pmatrix}=\displaystyle \frac{A^k_n}{k!}=\displaystyle \frac{n!}{k!(n-k)!}Cnk=(nk)=k!Ank=k!(nk)!n!
这里把组合数CnkC^k_nCnk用符号(nk)\begin{pmatrix}n\\k \end{pmatrix}(nk)表示,称为二项式系数。杨辉三角是二项式系数(nr)\begin{pmatrix}n\\r\end{pmatrix}(nr)的典型应用。杨辉三角是排列成如下三角形的数字:

						    1
						   1 1
						  1 2 1
						 1 3 3 1
						1 4 6 4 1

每一行从上一行推导而来。如果编程求杨辉三角第nnn行的数字,可以模拟这个推导过程,逐级递推,复杂度是O(n2)O(n²)O(n2)。不过,若改用数学公式计算,则可以直接得到结果,比用递推快多了,这个公式就是(1+x)n(1+x)^n(1+x)n。观察(1+x)n(1+x)^n(1+x)n的展开:
(1+x)0=1(1+x)^0=1(1+x)0=1
(1+x)1=1+x(1+x)^1=1+x(1+x)1=1+x
(1+x)2=1+2x+x2(1+x)^2=1+2x+x^2(1+x)2=1+2x+x2
(1+x)3=1+3x+3x2+x31+x)^3=1+3x+3x^2+x^31+x)3=1+3x+3x2+x3
每行展开的系数刚好对应杨辉三角每一行的数字。即:杨辉三角可以用(1+x)n(1+x)^n(1+x)n来定义和计算。
那么如何计算(1+x)n(1+x)^n(1+x)n?二项式系数(nk)=n!k!(n−k)!\begin{pmatrix}n\\k \end{pmatrix}=\displaystyle \frac{n!}{k!(n-k)!}(nk)=k!(nk)!n!就是(1+x)n(1+x)^n(1+x)n展开后的系数。它们的关系可以这样理解:(1+x)n(1+x)^n(1+x)n的第kkk项,实际上就是从nnnxxx中选出kkk个,这就是组合数(nk)\begin{pmatrix}n\\k \end{pmatrix}(nk)的定义。所以:
(1+x)n=∑k=1n(nk)kn (1+x)^n=\sum_{k = 1}^{n}\begin{pmatrix}n\\k \end{pmatrix}k^n (1+x)n=k=1n(nk)kn
这个公式称为二项式定理。
有了这个公式,在求杨辉三角第n行的数字时就可以用公式直接计算了,复杂度为
O(1)O(1)O(1)。不过,该公式中有n!n!n!,如果直接计算n!n!n!,由于太大,有可能溢出。例如n=30n=30n=3030!30!30!超过了long longlong\ longlong long的范围。此时可以利用(nk−1)\begin{pmatrix}n\\k-1 \end{pmatrix}(nk1)(nk)\begin{pmatrix}n\\{k} \end{pmatrix}(nk)的递推关系(nk)(nk−1)=n−k+1k\displaystyle\frac{\begin{pmatrix}n\\{k} \end{pmatrix}}{\begin{pmatrix}n\\{k-1} \end{pmatrix}}=\displaystyle\frac{n-k+1}{k}(nk1)(nk)=knk+1逐个推导,避免计算阶乘。

容斥原理

在计数时,有时情况比较多,相互有重叠。为了使重叠部分不被重复计算,可以这样处理:先不考虑重叠的情况,把所有对象的数目计算出来,然后减去重复计算的数目。这种计数方法称为容斥原理。例如一根长为60m60m60m的绳子,每隔3m3m3m做一个记号,每隔4m4m4m也做一个记号,然后把有记号的地方剪断,问绳子共被剪成了多少段?
容斥原理的解题思路是:

  1. 333的倍数有202020个,不算绳子两头,有:20−1=1920-1=19201=19个记号;
  2. 444的倍数有151515个;
  3. 既是333的倍数又是444的倍数的,有:60÷(3×4)=560÷(3×4)=560÷(3×4)=5个。
  4. 所以记号的总数量是:(20−1)+(15−1)−(5−1)=29(20-1)+(15-1)-(5-1)=29(201)+(151)(51)=29,绳子被剪成292929段。

概率与期望

概率和数学期望是概率论和统计学中的数学概念。
设有随机变量XXX,出现取值xix_ixi的概率是pip_ipi,把它们的乘积之和称为数学期望(均值),记为E(X):E(X):E(X):
E(X)=∑i=1nxipi E(X)=\sum_{i = 1}^{n}x_ip_i E(X)=i=1nxipi

E(X)E(X)E(X)是基本的数学特征之一,它反映了随机变量平均值的大小。
以妇女的生育率为例,假设某国有200020002000万个育龄妇女,不生育妇女有277277277万,一孩724724724万,二孩883883883万,三孩116116116万。记一个妇女的孩子数量是XXX,取值0、1、2、30、1、2、30123,概率分别是:277/2000=0.1385、724/2000=0.362、883/2000=0.4415、116/2000=0.058277/2000=0.1385、724/2000=0.362、883/2000=0.4415、116/2000=0.058277/2000=0.1385724/2000=0.362883/2000=0.4415116/2000=0.058。那么平均每个妇女生育的孩子数量如下:
E(X)=0×0.1385+1×0.362+2×0.4415+3×0.058=1.419E(X)=0×0.1385+1×0.362+2×0.4415+3×0.058=1.419E(X)=0×0.1385+1×0.362+2×0.4415+3×0.058=1.419
数学期望具有线性性质。有限个随机变量之和的数学期望等于每个变量的数学期望之和:E(X+Y)=E(X)+E(Y)E(X+Y)=E(X)+E(Y)E(X+Y)=E(X)+E(Y)
竞赛中求数学期望的题目一般都会用到它的线性性质。由于线性性质和DP的状态转移思想很相似,所以常常用DP来实现。

例如:一个软件有SSS个子系统,会产生nnnbugbugbug。现在要找出所有种类的bugbugbug。假设某人一天发现一个bugbugbug。一个bugbugbug属于某个子系统的概率是1S\displaystyle \frac{1}{S}S1,属于某种分类的概率是1n\displaystyle \frac{1}{n}n1,问发现nnnbugbugbug,且每个子系统都发现bugbugbug的天数的期望。0<n,s≤10000<n,s≤10000<n,s1000。给出n和sn和sns,求出数学期望。
分析
定义状态dp[i][j]dp[i][j]dp[i][j],它表示已经找到iiibugbugbug,并存在于jjj个子系统中,要达到目标状态还需要的期望天数。其中,dp[n][s]dp[n][s]dp[n][s]表示已经找到nnnbugbugbug,且存在于sss个子系统,说明已经达到了目标,还需要000天,所以dp[n][s]=0dp[n][s]=0dp[n][s]=0。从dp[n][s]dp[n][s]dp[n][s]倒推回dp[0][0]dp[0][0]dp[0][0],就是本题的答案,即还没有找到任何bugbugbug的情况下到达dp[n][s]dp[n][s]dp[n][s]时需要的期望天数。
dp[i][j]dp[i][j]dp[i][j]开始:后面111天找到111bugbugbug,可能有以下444种情况:

  1. dp[i][j]dp[i][j]dp[i][j]:发现一个bugbugbug,属于已经有的iii个分类和jjj个系统,概率为p1=(i/n)∗(j/s)p1=(i/n)*(j/s)p1=(i/n)(j/s)。这一天相当于浪费了。
  2. dp[i+1][j]dp[i+1][j]dp[i+1][j]:发现一个bugbugbug,不属于已有分类、属于已有系统,概率为:
    p2=(1−i/n)∗(j/s)p2=(1-i/n)*(j/s)p2=(1i/n)(j/s)
  3. dp[i][j+1]dp[i][j+1]dp[i][j+1]:发现一个bugbugbug,属于已有分类、不属于已有系统,概率为:
    p3=(i/n)∗(1−j/s)p3=(i/n)*(1-j/s)p3=(i/n)(1j/s)
  4. dp[i+1][j+1]dp[i+1][j+1]dp[i+1][j+1]:发现一个bugbugbug,不属于已有系统、不属于已有分类,概率为:p4=(1—i/n)∗(1−j/s)p4=(1—i/n)*(1-j/s)p4=(1—i/n)(1j/s)

可以验证:p1+p2+p3+p4=1p1+p2+p3+p4=1p1+p2+p3+p4=1
状态转移方程如下:
dp[i][j]=p1∗dp[i][j]+p2∗dp[i+1][j]+p3∗dp[i][j+1]+p4∗dp[i+1][j+1]+1 dp[i][j]=p1*dp[i][j]+p2*dp[i+1][j]+p3*dp[i][j+1]+p4*dp[i+1][j+1]+1 dp[i][j]=p1dp[i][j]+p2dp[i+1][j]+p3dp[i][j+1]+p4dp[i+1][j+1]+1
+1+1+1是因为末尾要加上111

整理得到:
dp[i][i]=(p2∗dp[i+1][i]+p3∗dp[i][j+1]+p4∗dp[i+1][j+1]+1)/(1−p1) dp[i][i]=(p2*dp[i+1][i]+p3*dp[i][j+1]+p4*dp[i+1][j+1]+1)/(1-p1) dp[i][i]=(p2dp[i+1][i]+p3dp[i][j+1]+p4dp[i+1][j+1]+1)/(1p1)
=(n∗s+(ni)∗j∗dp[i+1][j]+i∗(s−j)∗dp[i][j+1] =(n*s+(ni)*j*dp[i+1][j]+i*(s-j)*dp[i][j+1] =(ns+(ni)jdp[i+1][j]+i(sj)dp[i][j+1]
+(n−i)∗(s−j)∗[i+1][j+1])/(n∗s−i∗j) +(n-i)*(s-j)*[i+1][j+1])/(n*s-i*j) +(ni)(sj)[i+1][j+1])/(nsij)
在写程序时,从dp[n][s]dp[n][s]dp[n][s]倒推到dp[0][0]dp[0][0]dp[0][0]dp[0][0]dp[0][0]dp[0][0]就是答案。

    cin >> n >> s;
    for (int i = n; i >= 0; i--) {
        for (int j = s; j >= 0; j--) {
            if (i == n && j == s) {
                dp[n][s] = 0.0;
            } else {
		        dp[i][j] = (n * s + (n - i) * j * dp[i + 1][j] 
		        + i * (s - j) * dp[i][j + 1] +(n - i) * (s - j) 
		        * dp[i + 1][j + 1]) / (n * s - i * j);
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanxinfx2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值