多重集组合数dp
经典dp:多重集组合数
多重集组合数问题
- 一个有关计数的动态规划问题,含有优化的数学推导过程,蛮有意思的,就是太巧妙了,
蒟蒻的自己肯定想不到,记录下。
问题描述
有$n$种物品,第$i$种物品有$a_i$个,不同种类的物品可以相互区分,但相同种类的物品无法区分。现在从这些物品中取出$m$个,有多少种取法?答案需要模M。
Sample Input
1
23 3
1 2 3Sample Output
1
6
样例解释:
有n=3种物品, 每种a={1,2,3}个, 取出m=3个, 取法result=6(0+0+3, 0+1+2, 0+2+1, 1+0+2, 1+1+1, 1+2+0).
思路&解法
很容易想到状态$dp[i][j]$表示前$i$种物品取$j$个的方法总数,状态转移方程为:
意思是:先从前$i-1$种物品中取$j-k$个,再从第$i$种物品种取$k$个,因此方法总数就是先从前$i-1$种物品中取$j-k$个的方法总数,这里需要注意$k$的上界是$j$和$a[i]$两者中的较小者(既要保证$j-k>0$,也要保证合法)。
时间复杂度为:$O(nm^2)$,可以开始搞了。
AC代码($O(nm^2)$)
1 |
|
优化
发现这个时间复杂度不是很给力,看看能不能再做点优化?
考虑状态转移方程:
将其右边展开,分类讨论:
- $j\leq a\left[i\right]$时:显然,括号内就是合并两式,得到:
- $j>a\left[i\right]$时:
于是,仿照1中的格式,写出一个类似的式子如下,方便合并:
我们把它展开:
发现等号右边多了一个$dp[i-1][j-a[i]-1]$,所以在合并的时候,需要在等号右边减掉,得出最终的状态转移方程如下:
可以用$O(nm)$的时间复杂度搞它。
AC代码($O(nm)$)
1 |
|
- 此题为我们提供了一条优化$dp$方程的思路,即通过对方程求和式的展开进一步探索其与之前状态的联系,从而优化了时间复杂度,值得借鉴。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!