10.3 其他数学专题

10.3.1 递推

汉诺塔问题。假设有A、B、C 3个轴,有n个直径各不相同、从小到大依次编号为1, 2, 3,…,n的圆盘按照上小下大的顺序叠放在A轴上。现要求将这n个圆盘移至B轴上并仍按同样顺序叠放,但圆盘移动时必须遵循下列规则:

 

【分析】

这个问题看上去很容易,但当n稍大一点时,手工移动就开始变得困难起来。下面直接给出递归解法:首先,把前n-1个圆盘放到C轴;接下来把n号圆盘放到B轴;最后,再把前n-1个盘子放到B轴,如图10-5所示。

图10-5 根据递归解法建立汉诺塔的递推关系

图10-4中还给出了n个圆盘所需步数f(n)的递推式:f(n)=2f(n-1)+1。如果把f(n)的值从小到大列出来,即1,3,7,15,31,63,127,255…,你会发现其实有一个简单的表达式:f(n)=2n-1。

用数学归纳法不难证明:f(1)=1满足等式。假设n=k满足等式,即f(k)=2k-1,则n=k+1时,f(k+1)=2f(k)+1=2(2k-1)+1=2k+1-2+1=2k+1-1。因此n=k+1也满足等式。由数学归纳法可知,n取任意正整数均成立。

如果还不熟悉数学归纳法,其实从上面的证明过程已经能看出来其基本原理——其实它正是一种递归证明。只要边界处理好(f(1)=1满足),递归时缩小规模(用k来证明k+1),然后在“相信递归”(假设n=k成立)的前提下证明即可。

提示10-6:数学归纳法是一种利用递归的思想证明的方法。如果要讨论的对象具有某种递归性质(如正整数),可以考虑用数学归纳法。

Fibonacci数列。先来考虑一个简单的问题:楼梯有n个台阶,上楼可以一步上一阶,也可以一步上两阶。一共有多少种上楼的方法?

这是一道计数问题。在没有思路时,不妨试着找规律。n=5时,一共有8种方法:


5=1+1+1+1+1
5=2+1+1+1
5=1+2+1+1
5=1+1+2+1
5=1+1+1+2
5=2+2+1
5=2+1+2
5=1+2+2

其中有5种方法第1步走了1阶(灰色),3种方法第1步走了2阶。没有其他可能了。假设f(n)为n个台阶的走法总数,把n个台阶的走法分成两类。

第1类:第1步走1阶。剩下还有n-1阶要走,有f(n-1)种方法。

第2类:第1步走2阶。剩下还有n-2阶要走,有f(n-2)种方法。

这样,就得到了递推式:f(n)=f(n-1)+f(n-2)。不要忘记边界情况:f(1)=1,f(2)=2。当然,也可以认为边界是f(0)=f(1)=1。把f(n)的前几项列出:1, 1, 2, 3, 5, 8,…。

再例如,把雌雄各一的一对新兔子放入养殖场中。每只雌兔从第2个月开始每月产雌雄各一的一对新兔子。试问第n个月后养殖场中共有多少对兔子?

还是先找找规律。

第1个月:一对新兔子r1。用小写字母表示新兔子。

第2个月:还是一对新兔子,不过已经长大,具备生育能力了,用大写字母R1表示。

第3个月:R1生了一对新兔子r2,一共两对。

第4个月:R1又生一对r3,一共3对。另外,r2长大了,变成R2

第5个月:R1和R2各生一对,记为r4和r5,共5对。此外,r3长成R3

第6个月:R1、R2和R3各生一对,记为r6~r8,共8对,同时r4到r5长大。

……

把这些数排列起来:1, 1, 2, 3, 5, 8, …,和刚才的一模一样!事实上,可以直接推导出递推关系f(n)=f(n-1)+f(n-2):第n个月的兔子由两部分组成,一部分是上个月就有的老兔子,一部分是上个月出生的新兔子。前一部分等于f(n-1),后一部分等于f(n-2)(第n-1个月时具有生育能力的兔子数就等于第n-2个月的兔子总数)。根据加法原理,f(n)=f(n-1)+f(n-2)。

提示10-7:满足F1=F2=1,Fn=Fn-1+Fn-2的数列称为Fibonacci数列,它的前若干项是1, 1, 2, 3, 5, 8, 13, 21, 34, 55,…。

再例如,有2行n列的长方形方格,要求用n个1*2的骨牌铺满。有多少种铺法?

考虑最左边一列的铺法。如果用一个骨牌直接覆盖,则剩下的2*(n-1)方格有f(n-1)种铺法;如果是用两个横向骨牌覆盖,则剩下的2*(n-2)方格有f(n-2)种方法,如图10-6所示。不难发现:第一列没有其他铺法,因此f(n)=f(n-1)+f(n-2)。边界f(0)=1, f(1)=1,恰好是Fibonacci数列。

图10-6 骨牌覆盖问题

这就是多数课本上讲解这道题目的方法,无须多说,因为重点并不在此。笔者曾想到过另一个解法,与各位读者分享:设第i列是纵向骨牌,则左边i-1列和右边n-i列各有f(i-1)和f(n-i)种铺法。根据乘法原理,一共有f(i-1)f(n-i)种铺法。然后把i=1,2,3,…,n的情形全部加起来,根据加法原理,有:

f(n)=f(0)f(n-1) + f(1)f(n-2)+…+f(n-1)f(0)

这个递推式对不对呢?聪明的读者也许已经看出,这个解法存在两个问题:

(1)有遗漏。只考虑了第1,2,3,…,n列是纵向骨牌的情形,但实际上可能所有的骨牌都是横向的。当且仅当n为偶数时,恰好有一种这样的方案。

(2)有重复。根据“第i列有骨牌”对所有方案进行了分类,但其实这些方案是有重叠的。例如,第1列和第2列完全可以同时有骨牌。这些方案在递推式中被重复计算了。

既然如此,这个思路是不是走入死胡同了呢?不是的!只要把刚才的推理变得严密起来,同样可以得到一个正确的递推式:根据从左到右第一条纵向骨牌的列编号分类。如果不存在,当且仅当n为偶数时有一种方案;当第一条纵向骨牌的列编号为i时,意味着左边i-1列必须全部是横向骨牌——当i为奇数时恰好有一个方案。而右边n-i列则可以用任意铺法,共f(n-i)种。换句话说:

n为偶数时,f(n)=f(n-1)+f(n-3)+f(n-5)…+f(1)+1(最后加上的就是“没有纵向骨牌”的情形)。

n为奇数时,f(n)=f(n-1)+f(n-3)+f(n-5)…+f(2)+ f(0)。

边界是f(0)=f(1)=1。我们已经知道,问题的答案应该是Fibonacci数列,自然会对这个复杂的递推式产生怀疑:它真的是正确的吗?

带着这个疑问,笔者写了一个程序。结果出乎意料:居然和Fibonacci数列一样!事实上,它确实是Fibonacci数列。Fibonacci数列拥有很多有趣的性质,有兴趣的读者可以在网上搜索更多相关资料。不管怎样,这个“旧题新解”至少说明了两点:

(1)一个数列可能有多个看上去完全不同的递推式。

(2)即使是漏洞百出的解法也有可能通过“打补丁”的方式修改正确。

Catalan数。给一个凸n边形,用n-3条不相交的对角线把它分成n-2个三角形,求不同的方法数目。例如,n=5时,有5种剖分方法,如图10-7所示。

图10-7 凸五边形的5种三角剖分

【分析】

设答案为f(n)。按照某种顺序给凸多边形的各个顶点编号为V1,V2,…, Vn。既然分成的是三角形,边V1Vn在最终的剖分中一定恰好属于某个三角形V1VnVk,所以可以根据k进行分类。不难看出,三角形V1VnVk的左边是一个k边形,右边是一个n-k+1边形(如图10-8(a)所示)。根据乘法原理,包含三角形V1VnVk的方案数为f(k)f(n-k+1);根据加法原理有:

f(n)=f(2)f(n-1) + f(3)f(n-2) +…+ f(n-1)f(2)

边界是f(2)=f(3)=1。不难算出从f(3)开始的前几项f值依次为:1、2、5、14、42、132、429、1430、4862、16796。

提示10-8:在建立递推式时,经常会用到乘法原理,其核心是分步计数。如果可以把计数分成独立的两个步骤,则总数量等于两步计数之乘积。

另一种思路是考虑V1连出的对角线。对角线V1Vk把凸n边形分成两部分,一部分是k边形,另一部分是n-k+2边形(如图10-8(b)所示)。根据乘法原理,包含对角线V1Vk的凸多边形有f(k)f(n-k+2)个。根据对称性,考虑从V2V3、…、Vn出发的对角线也会有同样的结果,因此一共有n(f(3)f(n-1)+f(4)f(n-2)+…+f(n-1)f(3))个部分。

 

  (a)     (b)  

图10-8 凸多边形三角剖分数目的两种递推方法

但这并不是正确答案,因为同一个剖分被重复计算了多次!不过这次不必去消除重复了,因为这些重复很有规律:每个方案恰好被计算了2n-6次——有n-3条对角线,而考虑每条对角线的每个端点时均计算了一次。这样,得到了f(n)的第2个递推式:

f(n) = (f(3)(n-1)+f(4)f(n-2)+…+f(n-1)f(3)n/(2n-6)

它和第一个递推式有几分相似,但又不同。把n+1代入第1个递推式后得到:

f(n+1)=f(2)f(n) + f(3)f(n-1) + f(4)f(n-2) +…+ f(n-1)f(3) + f(n)f(2)

灰色部分是相同的!根据第2个递推式,它等于f(n)•(2n-6)/n,把它和f(2)=1一起代入上式得:

这个递推式和前两个相比就简单多了。这个数列称为Catalan数,也是常见的计数数列。

例题10-13 危险的组合(Critical Mass, UVa580)

有一些装有铀(用U表示)和铅(用L表示)的盒子,数量均足够多。要求把nn≤30)个盒子放成一行,但至少有3个U放在一起,有多少种放法?例如,n=4, 5, 30时答案分别为3, 8和974791728。

【分析】

设答案为f(n)。既然有3个U放在一起,可以根据这3个U的位置分类——对,根据前面的经验,要根据“最左边的3个U”的位置分类。假定是ii+1和i+2这3个盒子,则前i-1个盒子不能有3个U放在一起的情况。设n个盒子“没有3个U放在一起”的方案数为g(n)=2n-f(n),则前i-1个盒子的方案有g(i-1)种。后面的n-i-2个盒子可以随便选择,有2n-i-2种。根据乘法原理和加法原理,

遗憾的是,这个推理是有瑕疵的。即使前i-1个盒子内部不出现3个U,仍然可能和ii+1和i+2组成3个U。正确的方法是强制让第i-1个盒子(如果存在)放L,则前i-2个盒子内部不能出现连续的3个U。因此,边界是f(0)=f(1)=f(2)=0。g(0)=1,g(1)=2,g(2)=4。注意上式中的2n-3对应于i=1的情况。

例题10-14 比赛名次(Race, UVa12034)

A、B两人赛马,最终名次有3种可能:并列第一;A第一B第二;B第一A第二。输入n(1≤n≤1000),求n人赛马时最终名次的可能性的个数除以10056的余数。

【分析】

设答案为f(n)。假设第一名有i个人,有C(n,i)种可能性,接下来有f(n-i)种可能性,因此答案为∑C(n,i)f(n-i)。

例题10-15 杆子的排列(Pole Arrangement, ACM/ICPC Daejeon 2012, UVa1638)

有高为1, 2, 3,…, n的杆子各一根排成一行。从左边能看到l根,从右边能看到r根,求有多少种可能。例如,图10-9中的两种情况都满足l=1,r=2(1≤lrn≤20)。

图10-9 杆子的排列

【分析】

d(i,j,k)表示让高度为1~i根杆子排成一行,从左边能看到j根,从右边能看到k根的方案数。为了方便起见,假定i≥2。如何进行递推呢?首先尝试按照从小到大的顺序按照各个杆子。假设已经安排完高度为1~i-1的杆子,那么高度为i的杆子可能会挡住很多其他杆子,看上去很难写出递推式。

那么换一个思路:按照从大到小的顺序安排各个杆子。假设已经安排完高度为2~i的杆子,那么高度为1的杆子不管放哪里都不会挡住任何一根杆子。有如下3种情况。

情况1:插到最左边,则从左边能看到它,从右边看不见(因为i≥2)。

情况2:如果插到最右边,则从右边能看到它,从左边看不见。

情况3(有i-2个插入位置):插到中间,则不管从左边还是右边都看不见它。

在第一种情况下,高度为2~i的那些杆子必须满足:从左边能看到j-1根,从右边能看到k根,因为只有这样,加上高度为1的杆子之后才是“从左边能看到j根,从右边能看到k根”。虽然状态d(i,j,k)表示的是“让高度为1~i的杆子……”,而现在需要把高度为2~i+1的杆子排成一行,但是不难发现:其实杆子的具体高度不会影响到结果,只要有i根高度各不相同的杆子,从左从右看分别能看到j根和k根,方案数就是d(i,j,k)。换句话说,情况1对应的方案数是d(i-1,j-1,k)。类似地,情况2对应的方案数是d(i-1,j,k-1),而情况3对应的方案数是d(i-1,j,k)*(i-2)。这样,就得到了如下递推式:

d(i,j,k) = d(i-1,j-1,k) + d(i-1,j,k-1) + d(i-1,j,k)*(i-2)

10.3.2 数学期望

数学期望。简单地说,随机变量X的数学期望EX就是所有可能值按照概率加权的和。例如,一个随机变量有1/2的概率等于1,1/3的概率等于2,1/6的概率等于3,则这个随机变量的数学期望为1*1/2+2*1/3+3*1/6=5/3。在非正式场合中,可以说这个随机变量“在平均情况下”等于5/3。在解决和数学期望相关的题目时,可以先考虑直接使用数学期望的定义求解:计算出所有可能取值,以及对应的概率,最后求加权和,如果遇到困难,则可以考虑使用下面两个工具:

期望的线性性质。有限个随机变量之和的数学期望等于每个随机变量的数学期望之和。例如,对于两个随机变量XYE(X+Y)=EX+EY

全期望公式。类似全概率公式,把所有情况不重复、不遗漏地分成若干类,每类计算数学期望,然后把这些数学期望按照每类的概率加权求和。

例题10-16 过河(Crossing Rivers, ACM/ICPC Wuhan 2009, UVa12230)

你住在村庄A,每天需要过很多条河到另一个村庄B上班。B在A的右边,所有的河都在中间。幸运的是,每条河上都有匀速移动的自动船,因此每当到达一条河的左岸时,只需等船过来,载着你过河,然后在右岸下船。你很瘦,因此上船之后船速不变。

日复一日,年复一年,你问自己:从A到B,平均情况下需要多长时间?假设在出门时所有船的位置都是均匀随机分布。如果位置不是在河的端点处,则朝向也是均匀随机。在陆地上行走的速度为1。

输入A和B之间河的个数n、长度D(0≤n≤10,1≤D≤1000),以及每条河的左端点坐标离A的距离p,长度L和移动速度v(0≤p<D,0<LD,1≤v≤100),输出A到B时间的数学期望。输入保证每条河都在A和B之间,并且相互不会重叠。

【分析】

用数学期望的线性。过每条河的时间为L/v到3L/v的均匀分布,因此期望过河时间为2L/v。把所有2L/v加起来,再加上D-sum(L)即可。

例题10-17 糖果(Candy, ACM/ICPC Chengdu 2012, UVa1639)

有两个盒子各有nn≤2*105)个糖,每天随机选一个(概率分别为p,1-p),然后吃一颗糖。直到有一天,打开盒子一看,没糖了!输入n, p,求此时另一个盒子里糖的个数的数学期望。

【分析】

根据期望的定义,不妨设最后打开第1个盒子,此时第2个盒子有i颗,则这之前打开过n+(n-i)次盒子,其中有n次取的是盒子1,其余n-i次取的盒子2,概率为C(2n-i, n)pn+1 (1-p)n-i。注意p的指数是n+1,因为除了前面打开过n次盒子1之外,最后又打开了一次。

这个概率表达式在数学上是正确的,但是用计算机计算时需要小心:n可能高达20万,因此C(2n-i, n)可能非常大,而pn+1和(1-p)n-i却非常接近0。如果分别计算这3项再乘起来,会损失很多精度。一种处理方式是利用对数,设v1(i) = ln(C(2n-i, n)) + (n+1)ln(p) + (n-i)ln(1-p),则“最后打开第1个盒子”对应的数学期望为ev1(i)

同理,当最后打开的是第2个盒子,对数为v2(i) = ln(C(2n-i, n)) + (n+1)ln(1-p) + (n-i)ln(p),概率为ev2(i)。根据数学期望的定义,最终答案为sum{i(ev1(i)+ev2(i))}。

例题10-18 优惠券(Coupons, UVa10288)

大街上到处在卖彩票,一元钱一张。购买撕开它上面的锡箔,你会看到一个漂亮的图案。图案有n种,如果你收集到所有nn≤33)种彩票,就可以得大奖。请问,在平均情况下,需要买多少张彩票才能得到大奖呢?如n=5时答案为137/12。

【分析】

已有k个图案, 令s=k/n, 拿一个新的需要t次的概率:st-1(1-s); 因此平均需要的次数为(1-s)(1 + 2s + 3s2 + 4s3 + …) = (1-s)E,而sE = s + 2s2 + 3s3 + … = E-(1+s+s2+…),移项得

(1-s)E=1+s+s2+…=1/(1-s) = n/(n-k)

换句话说,已有k个图案:平均拿n/(n-k)次就可多搜集一个, 所以总次数为:

n(1/n+1/(n-1)+1/(n-2)+…+1/2+1/1)

10.3.3 连续概率

连续概率。简单地说,随机变量X的数学期望EX就是所有可能值按照概率加权的和。例如,一个随机变量有1/2的概率等于1,1/3的概率等于2,1/6的概率等于3,则比变量随机。

例题10-19 概率(Probability, UVa11346)

在[-a,a]*[-b,b]区域内随机取一个点P,求以(0,0)和P为对角线的长方形面积大于S的概率(a,b>0,S≥0)。例如a=10,b=5,S=20,答案为23.35%。

【分析】

根据对称性,只需要考虑[0,a]*[0,b]区域取点即可。面积大于S,即xy>Sxy=S是一条双曲线,所求概率就是[0,a]*[0,b]中处于双曲线上面的部分。为了方便,还是求曲线下面的面积,然后用总面积来减,如图10-10所示。

图10-10 双曲线所围面积

设双曲线和区域[0,a]*[0,b]左边的交点P是(S/b, b),因此积分就是:

查得1/S的原函数是ln(S),因此积分部分就是ln(a)-ln(S/b)= ln(ab/S)。设面积为m,则答案为(m - s - s *ln(m/s)) / m

注意这样做有个前提,就是双曲线和所求区域相交。如果s>ab,则概率应为0;而如果s太接近0,概率应直接返回1,否则计算ln(m/s)时可能会出错。

例题10-20 你想当2n元富翁吗?(So you want to be a 2n-aire?, UVa10900)

在一个电视娱乐节目中,你一开始有1元钱。主持人会问你n个问题,每次你听到问题后有两个选择:一是放弃回答该问题,退出游戏,拿走奖金;二是回答问题。如果回答正确,奖金加倍;如果回答错误,游戏结束,你一分钱也拿不到。如果正确地回答完所有n个问题,你将拿走所有的2n元钱,成为2n元富翁。

当然,回答问题是有风险的。每次听到问题后,你可以立刻估计出答对的概率。由于主持人会随机问问题,你可以认为每个问题的答对概率在t和1之间均匀分布。输入整数n和实数t(1≤n≤30,0≤t≤1),你的任务是求出在最优策略下,拿走的奖金金额的期望值。这里的最优策略是指让奖金的期望值尽量大。

【分析】

假设你刚开始游戏,如果直接放弃,奖金为1;如果回答,期望奖金是多少呢?不仅和第1题的答对概率p相关,而且和答后面的题的情况相关。即:

选择“回答第1题”后的期望奖金 = p * 答对1题后的最大期望奖金

注意,上式中“答对1题后的最大期望奖金”和这次的p无关,这提示我们用递推的思想,用d[i]表示“答对i题后的最大期望奖金”,再加上“不回答”时的情况,可以得到:若第1题答对概率为p,期望奖金的最大值 = max{20, p*d[1]}

这里故意写成20,强调这是“答对0题后放弃”所得到的最终奖金。

上述分析可以推广到一般情况,但是要注意一点:到目前为止,一直假定p是已知的,而p实际上并不固定,而是在t~1内均匀分布。根据连续概率的定义,d[i]在概念上等于max{2i, p*d[i+1]}在p=t~1上的积分。不要害怕“积分”二字,因为虽然在概念上这是一个积分,但是落实到具体的解法上,仍然只需要基础知识。

因为有max函数的存在,需要分两种情况讨论,即p*d[i+1]<2ip*d[i+1]≥2i两种情况。令p0=max{t, 2i/d[i+1]}(加了一个max是因为根据题目,pt),则:

 

在第一种情况中,p的实际范围是[t,p0),因此概率为p1=(p0-t)/(1-t)。根据全期望公式,d[i] = 2i * p1 + (1+p0)/2 * d[i+1] * (1-p1)。

边界是d[n] = 2n,逆向递推出d[0]就是本题的答案。

例题10-21 多边形(Polygon, UVa11971)

有一根长度为n的木条,随机选k个位置把它们切成k+1段小木条。求这些小木条能组成一个多边形的概率。

【分析】

不难发现本题的答案与n无关。在一条直线上切似乎难以处理,可以把直线接成一个圆,多切一下,即在圆上随机选k+1个点,把圆周切成k+1段。根据对称性,两个问题的答案相同。

新问题就要容易处理得多了:“组不成多边形”的概率就是其中一个小木条至少跨越了半个圆周的概率。设这个最长的小木条从点i开始逆时针跨越了至少半个圆周,则其他所有点都在这半个圆周之外,如图10-11所示的灰色部分。

图10-11 木条逆时针跨越所成形状

除了点i之外其他每个点位于灰色部分的概率均为1/2,因此总概率为1/2k。点i的取法有k+1种,因此“组不成多边形”的概率为(k+1)/2k,能组成多边形的概率为1-(k+1)/2k