正睿国庆DAY2动态规划专题
排列-例题
1~n 的排列个数,每个数要么比旁边两个大,要么比旁边两个小
\(f[i][j]\) 填了前i个数,未填的数有\(j\)个比第\(i\)个小,是波峰
\(g[i][j]\)是波谷
\(f[i][j] -g[i+1][j']\)
\(g[i][j]-f[i+1][j']\)
可以前缀和优化
n个数的排列中恰好有k个位置满足\(a_i<a_{i+1}\)的个数
可能是今天唯一自己想出来的题了23333
\(f[i][j]\) 前i个数的排列有j个小于号的排列个数,并考虑插入第\(i+1\)个数
放最前面:\(f[i][j]->f[i+1][j]\)
放中间的小于号 :\(j*f[i][j] -> f[i+1][j]\)
放中间的大于号 :\((i-1-j)*f[i][j] -> f[i+1][j+1]\)
放最后面:\(f[i][j]->f[i][j-1]\)
然后可以搞组合计数优化
排列dp的处理总结:
- 枚举个数/剩余个数
- 插入法(通常更优)
优化复杂度
状态数
- 合理设计
- 去掉没有用的状态
转移
- 前缀和
- 数据结构优化
- 矩阵优化(递推)
- trivival -> non-trivival (改掉某些转移,便乘不显然的形式)
优化空间
- 滚动数组
继续例题
f[i]为\(1- i\)被覆盖的最小代价,用树状数组维护区间\(f\)最小值就可以了
即每行选一个数使得和最大
- 普通dp: \(3^n*m\)
- 每一列只需要考虑前n个最大的
- 考虑每列循环移位同样的步数答案都一样,可以优化成\(2^nn^2\)
\(n\) 个数排列中恰好有 \(k\) 个峰的方案数,\(\pmod {239}\)
\(n\leq 10^{15},k\leq 30\)
\(f[i][j]\) 前\(i\)个数,有\(j\)个峰,考虑添加第\(i+1\)个数
- 搞掉前面的一个峰:\(f[i+1][j]+=f[i][j]*2j\)
- 否则\(f[i+1][j+1]+=f[i][j]*(i+1-2*j)\)
可以写成矩阵乘法,且\(M_i=M_i+239\)