隔板法
隔板法
对于n个非负变量x1,x2,…,xn,问满足下面等式的分配方案有多少种:
x1+x2+…+xn=m这等价于m个小球,我们向其中插入n−1个挡板,将其切分为n部分的方案数,因此我们可以直接得出方案数为:
(m+n−1n−1)现在考虑满足下面不等式的分配方案有多少种:
L≤x1+x2+…+xn≤R我们现在进行推导:
R∑i=L(i+n−1i)=R∑i=L(i+n−1i)+(L+n−1L−1)−(L+n−1L−1)=R∑i=L+1(i+n−1i)+(L+n−1L)+(L+n−1L−1)−(L+n−1L−1)=R∑i=L+1(i+n−1i)+(L+nL)−(L+n−1L−1)…=(R+nR)−(L+n−1L−1)现在考虑一个更简单的不等式的分配方案:
x1+x2+…+xn≤m进行推导:
m∑i=0(i+n−1i)=m∑i=1(i+n−1i)+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)=∏i∈Axi。现在要求求对于所有大小为k的下标集合,计算所有方案下它们权重的总和。
由于这些变量仅仅指标不同,因此对于两个大小均为k的下标集合,它们在所有方案下权重之和应该是相同的。于是乎我们要考虑在所有方案下,∏1≤i≤kxi的值的和,最后乘上(nk)就是我们要求的结果了。
现在考虑怎么计算∏1≤i≤kxi,DP当然可以,但是时间复杂度为O(n2)。也可以用生成函数,但是有点复杂,而且时间复杂度也好不到哪里去。
这个问题实际上有O(1)的做法(不考虑预处理O(n)时间)。非常简单,这个问题等价于将一个长度为m个线段分解为n个长度为整数的线段,且前k个线段需要从中间某个整数位置(不能和左边界重合)再选择一个中间点,问最终有多少不同的方案(长度为L的线段,选择中间点有L种可能)。而这个问题等价于直接将原序列拆分成n+k段,其中特定的k段不能为空。这个可以通过隔板法解决,即(n+m−1n+k−1)。
题目2:考虑这样一个问题,有n个非负偶数x1,…,xn和m个非负奇数y1,…,ym,要求计算有多少种不同的赋值方案,满足x1+…+xn+y1+…+ym≤K。将结果模上某个素数p。其中0≤n,m≤100,K≤1018。
我们额外加入一个非负变量z,因此问题要我们计算有多少不同的赋值方案,满足x1+…+xn+y1+…+ym+z=K。
一般的思路是用生成函数来求解,但是不好求解。
我们可以发现n,m非常小,因此我们可以考虑用动态规划来求解。记dp(i,j)表示前j个未知数总和为i的方案赋值数,那么我们可以用动态规划来求解,时间复杂度为O((n+m)K)。
但是仔细观察可以发现动态规划的递推公式是线性关系。即有A⋅dp(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)。
提供一道题目。