隔板法

Published: by Creative Commons Licence

  • Tags:

隔板法

对于n个非负变量x1,x2,,xn,问满足下面等式的分配方案有多少种:

x1+x2++xn=m

这等价于m个小球,我们向其中插入n1个挡板,将其切分为n部分的方案数,因此我们可以直接得出方案数为:

(m+n1n1)

现在考虑满足下面不等式的分配方案有多少种:

Lx1+x2++xnR

我们现在进行推导:

Ri=L(i+n1i)=Ri=L(i+n1i)+(L+n1L1)(L+n1L1)=Ri=L+1(i+n1i)+(L+n1L)+(L+n1L1)(L+n1L1)=Ri=L+1(i+n1i)+(L+nL)(L+n1L1)=(R+nR)(L+n1L1)

现在考虑一个更简单的不等式的分配方案:

x1+x2++xnm

进行推导:

mi=0(i+n1i)=mi=1(i+n1i)+1=(m+nm)(n0)+1=(m+nm)

其实这个问题也等价于下面等式成立的前提下,前n个变量有多少种分配方案。

x1+x2++xn+xn+1=m

由于前n个变量唯一决定变量xn+1,因此等于等式的总分配数。

题目1:考虑所有非负整数变量x1,,xn的赋值方案,要求满足x1++xn=m。考虑某个赋值方案,记任意一个下标集合A,定义这个下标集合的权重为w(A)=iAxi。现在要求求对于所有大小为k的下标集合,计算所有方案下它们权重的总和。

由于这些变量仅仅指标不同,因此对于两个大小均为k的下标集合,它们在所有方案下权重之和应该是相同的。于是乎我们要考虑在所有方案下,1ikxi的值的和,最后乘上(nk)就是我们要求的结果了。

现在考虑怎么计算1ikxi,DP当然可以,但是时间复杂度为O(n2)。也可以用生成函数,但是有点复杂,而且时间复杂度也好不到哪里去。

这个问题实际上有O(1)的做法(不考虑预处理O(n)时间)。非常简单,这个问题等价于将一个长度为m个线段分解为n个长度为整数的线段,且前k个线段需要从中间某个整数位置(不能和左边界重合)再选择一个中间点,问最终有多少不同的方案(长度为L的线段,选择中间点有L种可能)。而这个问题等价于直接将原序列拆分成n+k段,其中特定的k段不能为空。这个可以通过隔板法解决,即(n+m1n+k1)

题目2:考虑这样一个问题,有n个非负偶数x1,,xnm个非负奇数y1,,ym,要求计算有多少种不同的赋值方案,满足x1++xn+y1++ymK。将结果模上某个素数p。其中0n,m100K1018

我们额外加入一个非负变量z,因此问题要我们计算有多少不同的赋值方案,满足x1++xn+y1++ym+z=K

一般的思路是用生成函数来求解,但是不好求解。

我们可以发现n,m非常小,因此我们可以考虑用动态规划来求解。记dp(i,j)表示前j个未知数总和为i的方案赋值数,那么我们可以用动态规划来求解,时间复杂度为O((n+m)K)

但是仔细观察可以发现动态规划的递推公式是线性关系。即有Adp(i,?)=dp(i+1,?),其中A是一个R×R的矩阵,其中R=401

于是问题的时间复杂度为O(R3log2K),过有些勉强。

这里可以考虑用BM算法来优化。我们可以用O(R2)的时间复杂度搞出前面2R项,之后用BM算法推出最短递推公式。之后用多项式快速模O(R2log2K)求解。

提供一道题目:https://atcoder.jp/contests/aising2020/tasks/aising2020_f

题目3:给定n个非负整数a1,,an,记非负整数序列b1,,bn合法当且仅当它们的和不超过m。现在希望对所有可能的b序列,计算下式:ni=1(biai),并输出它们的和。

仔细观察,问题实际上要我们将m个排序的球分成n+1段,之后第i段球取ai个球进行标记,其余球另外进行标记。问能产生多少不同的标记序列。

我们可以通过插入隔板的方式,先加入n个球,第i个球用于隔开第i和第i+1段。之后我们还需要总共从m+n个球中选择n+ni=1ai个特殊的球进行标记,第一段为第a1+1个标记的球左边部分,第二段为a1+1个标记的球右边同时在第a1+a2+2个标记的球左边,其余类似。

所以总共可以产生的序列数目为(m+nn+ni=1ai)

提供一道题目