codeforces 2200左右dp题目练习
1. CF296B Yaroslav and Two Strings
白给题,令 \(f_{i,0/1,0/1}\) 表示前 \(i\) 位,有无小于,有无大于,根据每位的字符转移即可。
2. CF229D Towers
考虑设 \(f_i\) 表示前 \(i\) 个塔段数最多的划分,我们可以发现这个划分中最后一个数比其他划分都小,那么直接用 \(g_i\) 记录出最小值,然后可以直接 \(O(n)\) 转移,总共是 \(O(n^2)\) 的。
3. CF223B Two Strings
先正着倒着跑一遍匹配,对于 \(t\) 中的每个字符就可以搞出其最早/最晚在 \(s\) 中出现的位置,那么对于 \(s\) 中的 \(s_i\),只要存在一个 \(j\) 使得 \(t_j=s_i\) 并且 \(t_{j-1} \text{最早的位置} \le i \le t_{j+1} \text{最晚的位置}\) 就可以了,换句话说,在这个范围内的字符 \(s_i\) 都是合法的,那么我们考虑可以对每个字符单独考虑,for t 的所有位置,然后区间减一,最后判有没有位置大于 \(0\) 就行了。
这是 dp?
4. CF82D Two out of Three
考虑到状态是后缀加上一个数,直接转移就行。
5. CF855C Helga Hufflepuff's Cup
\(f_{u,0/1/2}\) 表示以 \(u\) 为根的子树中,\(u\) 的颜色是小于/等于/大于 \(k\) 时的方案数。
转移树上背包即可。
7. CF427D Match & Catch
枚举 LCP 长度跑哈希,但是 CF 有点抽象,整了一堆逆天数据,但是可以发现如果枚举比较大的话一般都是无解的,加上一个 if ((double)clock() / CLOCKS_PER_SEC > 0.95)
之类的就过了。
8. CF222E Decoding Genome
显然的一个 dp 是说考虑 \(f_{i,j}\) 表示前 \(i\) 位,且第 \(i\) 位的字符是 \(j\) 的方案数,考虑到每次转移相当于给 \(f_i\) 这个列向量左乘上一个矩阵,直接矩阵快速幂即可。
矩阵具体来说的构造是,如果存在限制 xy
,那么 \(a_{y,x}=0\) 剩下位置是 \(1\)。
9. CF533B Work Group
树形dp,\(f_{u,0/1}\) 表示 \(u\) 为根,\(u\) 的子树中选了偶数/奇数个点的情况;
转移就当作一个 size 在 mod 2 意义下的树形背包就行,时间复杂度 \(O(n)\)。
10. CF893E Counting Arrays
两个做法
- 一个大力 dp,\(f_{i,j}\) 处理出 \(i\) 个非 \(1\) 数乘起来是 \(j\) 的方案数,这个是 \(O(n\log^2n)\) 的。
每次询问的时候枚举出来选了 \(i\) 个非 \(1\) 数,贡献就是 \(f_{i,m}*\binom{n}{i}\),最后乘一个 \(2^{n-1}\)。 - 考虑对 \(m\) 质因数分解后对每个质因子分配,每个都是插板算贡献,最后乘 \(2^{n-1}\)。
11. CF1201D Treasure Hunting
考虑到每行结束后一定位于最左边或者最右边,转移二分出最近的上升列大力分类讨论。
细节比较多。
12. CF797E Array Queries
对于 \(k<=B\),预处理 \(f_{p,k}\) 表示当询问 \(p,k\) 时的答案,预处理时间复杂度 \(O(nB)\);
对于 \(k>B\) 暴力,单次询问时间复杂度 \(O(\frac{n}{B})\)。
取 \(B=\sqrt{n}\),时间复杂度为 \(O((n+q)\sqrt{n})\)。
这是 dp?
13. CF1067A Array Without Local Maximums
设 \(dp(i,j,0/1)\) 表示前 \(i\) 个数,\(a_i=j\),第 \(i-1\) 个数大 \(\ge a_i\) 还是 \(< a_i\) 的方案数。转移前后缀和优化即可,时间复杂度 \(O(nV)\)。
14. CF9D How many trees?
注意到 \(>=h\) 的限制比较困难,考虑转化成总数 \(-\) 高度 \(<h\) 的二叉树个数。
设 \(dp(i,j)\) 表示 \(i\) 个点,高度 \(\le j\) 的二叉树个数。
转移枚举左右子数的点数 \(dp(i,j)=\sum_{l+r=i-1}dp(l,j-1)dp(r,j-1)\),时间复杂度 \(O(n^2)\)。
15. CF633D Fibonacci-ish
暴力枚举 \(f_0,f_1\) 即可,注意加入一些剪枝,例如相同对子只算一次。
这是 dp?
16. CF1082E Increasing Frequency
用 \(f(i,v)\) 表示 \([1,i]\) 中 \(v\) 的出现次数。
不妨设 \([l,r]\) 区间把 \(a_r\) 调整成 \(c\) (否则可以减小 \(r\)),那么就是要最大化 \(f(l-1,c)+f(n,c)-f(r,c)+f(r,a_r)-f(l-1,a_r)\)。
枚举 \(r\),只要最大化 \(f(l-1,c)-f(l-1,a_r)\),令 \(g(v)=\max_{0\le i\le r-1}\{f(i,c)-f(i,v)\}\),所求即 \(g(a_r)\),问题转化成维护 \(g\)。
由于 \(g(v)\) 的最优决策点一定可以是某个 \(v\) 的前一个,因此可以只在 \(v\) 出现的时候更新 \(g(v)\)。也就是每次只用 \(f(r-1,c)-f(r-1,a_r)\) 更新 \(g(a_r)\) 即可。
时间复杂度 \(O(n+V)\)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端