珍珠项链

f[i][j]表示用i种珍珠构成长度为j的项链的种数

如果此时我们以珍珠的种类为考虑对象,枚举第i种珍珠的数量,那么有f[i][j]=l=1ji+1f[i1][jl]×Cjl

会发现这样完全推不走,因为n太大了

看到n这么大一般都是矩阵乘法,所以我们考虑用矩阵加速递推

由于矩阵快速幂要求向量长度不长但是变化时间很长,所以这里我们要把i作为向量长度,j作为变化时间,所以要考虑最后一个珠子是什么(这样递推的时候才只会用到j1的数据)(这也是分组DP的常用trick,不去考虑最后一个组是什么,而去考虑最后一组最后一个是什么)

f[i][j]=k=1if[i1][j1]+f[i][j1]=i(f[i1][j1]+f[i][j1])

前面一项是考虑我最后一个珠子放编号为k的珠子而且这个珠子是第一次出现(注意由编号为1,2,3...k1,k+1,k+2...i组成长度为j1的珠子与由编号为1,2,3...i1组成长度为j1的珠子是等价的)

后面一项是我考虑最后一个珠子放编号为k的珠子而且这个珠子在前j1个珠子中已经出现过了

现在还有一个问题,就是题目要求的是长度不超过N的项链,但是我们求得是刚好等于N的,怎么解决?

有两种解决方案,我先讲讲第一种,第二种放到老板的解决方法讲

第一种方法就是改状态:设f[i][j]表示用i种珍珠构成长度不超过j的项链的种数

这时只有f[1][j]=f[1][j1]+1改变了一下,f[2+][j]之后的状态转移方程都不变

所以就可以写出一个转移矩阵:

注意这是k+1阶矩阵

然后上矩阵快速幂就好了

然后来看看老板的做法

我们的DP状态一般是不会考虑这个状态之外的全局的东西的,他这里考虑了:这里的j种珍珠指的是从所有的k种珍珠任选j种珍珠组成的方案数的总和(比如(k(j1))dp[i1][j1]指的就是已经选了j1种珍珠在前i1个里面,再从剩下的kj+1种珍珠里面选一个放在最后)(这个要从刷表法的角度去理解,这种DP的形式还是比较新了,填表法的形式刷表法的理解)

然后介绍第二种方法:在向量中添加一个元素表示前缀和

posted @   最爱丁珰  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示