DP Problems
考虑到 Topcoder AC 不方便,所以 Topcoder 的都没写()
1.CF1152F2 Neko Rules the Catniverse (Large Version)
题意: 给定 ,求满足条件整数序列 个数:
-
。
-
-
互不相同。
。
思路:
我们发现,三个条件中最难的是 互不相同,这意味着我们如果按照 顺序 dp 将极其困难。
所以我们考虑按照值域的顺序来 dp,这里常见的计数就是插入的方法。
我们从大到小考虑,每次假设插入当前这个数,对于一个序列,我们可以插入在末尾或者某个数前面。
考虑到这个数是当前最小的,末尾肯定可以。
而如果在某个数后面就需要后面的数满足 当前这个数。
所以我们不妨设 表示考虑到 ,已经有了 个数,并且 这个范围内的情况是 ,每次转移乘上 即可。
然后发现这个可以用矩阵加速转移。就做完了。
2.GYM100377H Petya and arrays 加强版
题意: 求满足以下条件的 长度整数数组:
-
每个数都属于 。
-
连续的子数组的和不是 的倍数。
对 取模。
。
思路:
首先第二个性质的形式显然是将数组转化成前缀和。意味着不存在 。
所以我们不妨将前缀和对 取模。现在就是不能有相等的。
同时我们还发现要求不能有 。
我们不妨将所有的 向 连边,这样会形成若干个环。
现在变成了我们需要按顺序在这些环上选取一些数,要求有相邻的不能相邻的选。
我们不妨对每个环 dp 算出在这个环选若干个组成序列的方案数。
考虑到 很小,我们还是可以以插入的形式,不妨设 表示当前在环上按顺序考虑了 个点,已经选了 个,第一个元素和 的状态是 。
转移很好转移,同样可以矩阵快速幂优化,算答案时看一下 即可。
考虑到所有环都是相同的,我们只用计算 个环的贡献即可。这里可以用背包,最后容斥和组合数算一下即可。
(不保证正确性)
3.Topcoder10741 Colorful Maze
题意:
有一个 迷宫,包括障碍物和空格,其中空格都有一个颜色 。
每种颜色有概率 是危险的。如果进入一个危险颜色的格子两次就会死亡。
现在给定起点和终点和地图,求最优策略下活着走到终点的最大概率。
思路:
显然最优策略不是固定的,于是我们考虑设计 dp 状态。
对于这种概率 dp,更好的方式是从起点往回推。
设 表示从 出发,已经确认了 是安全的, 是危险的(如果没有则 ),求走到终点的最大概率。
我们枚举走到的下一个格子转移即可。
但是问题在于如果我们走到一个 mask 中的格子就将陷入死循环。
为此我们需要将所有相同颜色的格子所称一个大点来 dp 即可。
4.P2150 [NOI2015] 寿司晚宴
题意:
选取两个集合 满足:
-
。
-
不存在 使得 且 与 不互质。
。
思路:
经典题。
我们考虑将 的质因子集合记作 ,不难发现 。
但是质数的个数太多了,不好 dp。
我们发现,如果将质数按照 和 分类,则每个数至多含有一个二类质数!
而枚举一下发现一类质数个数最多 个。
所以我们可以把每个数划到其二类质数的那一类,现在问题转化为:每一类只能一个集合选,且一类质数不冲突。
于是我们对一类质数状压即可。时间复杂度 。
5.UOJ86 mx的组合数
题意:
对于 ,分别求 且 的个数,对 取模。
。
思路:
Lucas 定理非常厉害的应用。对于模数很小的情况 Lucas 定理会很有用。
我们考虑 Lucas 定理的等价形式:不妨设 ,则:
然后明显这道题就变成了一个数位 dp 题。
我们不妨设 表示当前考虑了前 位,组合数乘起来模 是 ,是否贴着上界。
转移需要枚举下一位的所有选择,时间复杂度为 。但是显然是过不去的。
我们发现如果我们把乘法转换成原根的加法,这将是一个卷积的形式,并且模数 支持 NTT,所以用 NTT 优化即可做到 了。
但是我们无法计算 0 的方案数,但是我们也只无法计算 0 的方案数,最后用总数减去即可。
注意差分的时候如果 也要减去 0 的贡献。
6.POJ1090 Chain
题意:
现在有一个长为 的 01 串,每次可以执行下面两种操作之一:
-
找到最右边的 1 并反转其左边的元素。
-
反转最后一位。
求最少几次变成 0。
思路:
首先我们需要观察:连续两次同种操作会抵消,所以操作一定是交替进行的。
所以只有两种可能,并且我们发现每种操作都会减少或增加一个 1,所以这其实就是格雷码!
我们知道,第 个的格雷码是 ,所以我们可以倒退出其是第几个格雷码。
注意到标准格雷码是一个环,有两种方法到起点,都要考虑。
7.Topcoder13457 BoardFolding
题意:
有一个 的 01 矩阵,可以横着或竖着对折,要求重叠部分完全一样,求最后能折成的最小面积。
(实际可以做到 )
思路:
一个很自然的想法是 表示 这个矩形是否可行。
转移枚举一下对折线即可,时间复杂度 。
我们考虑优化,通过观察,我们发现一个事情:横着对折和竖着对折互不影响。
所以我们可以分成 和 ,表示只考虑一种方向的对折是否可行,最后乘起来即可。
进一步,我们可以直接变成 , 表示 是否可行和 是否可行,然后乘起来。
用 Manacher 来转移,时间复杂度 。
8.CF111C Petya and Spiders
题意:
有一个 的矩阵,每个格子有一只蜘蛛,每只蜘蛛可以往上下左右移动一格或者不移动,求最多空出多少个格子。
。
思路:
根号分治得到 ,所以我们可以状压 dp。
设 表示到第 行的都确定了,当前第 行和第 行的状态是 。
如果直接枚举第 行的话需要枚举 ,转移如下:
但是时间复杂度是 ,显然不行。
发现 其实不会关心转移,所以我们对 记录最小的 即可。
时间复杂度 。
9.[AGC012E] Camel and Oases
题意:
直线上有 个点 和一个数字 ,两个点可达当且仅当其距离小于等于 。
从一个点出发,可以到达其所有直接或间接可达的点,或者跳跃到任何一个点,但是这样的话就会使得 。
求每个点出发能否访问所有点。
。
思路:
显然 的取值总共有 个,我们就是要把这些点分成 组,使得每组互相可达的最小的 不超过分配给这个组的长度。
所以我们考虑状压 dp,不妨设 表示如果用 中的长度,最长能覆盖的前缀。 则表示后缀。
我们通过枚举下一个长度和预处理可以计算出这两个值。
然后我们发现对于一个点,假设其最近不能覆盖到的是 ,则我们需要找到 满足 ,这显然是充分的。
于是二维数点即可。
时间复杂度 。
10.CF678E Another Sith Tournament
题意:
个人决斗,你知道每两个人之间彼此获胜的概率,你先选两个人决斗,赢的人继续和你再次选的人决斗(你可以根据上次结果来选),求最后 1 号获胜的最大概率。
。
思路:
首先这是一道概率问题,我们发现,如果我们知道了当前的人是 ,现在还未决斗的人的集合是 ,那么我们应该有一个最优策略是的我们会选一个 与 决斗。
所以我们不妨设 表示最大的概率,那么我们现在要做的就是选一个 ,使得决斗后的概率最大。
明显有 ,则我们最后只用看最开始选哪个人即可。
时间复杂度是 ,关键在于什么状态会确定最优策略。
11.CF1342F Make It Ascending
题意:
将 划分成 ,设 ,要求 且存在 使得 。
。
思路:
显然是用状压 dp,我们思考一下哪些东西会影响状态:当前已经选了的元素,总共选了多少个集合,上一个的代表,上一个集合的权值。
只要知道这些就能转移,但是显然不能都存下来,我们发现题目特征是单调递增的序列,这让我们想到 LIS 的二分算法,所以我们可以记 表示选了 个集合,上一个代表是 ,用了 中的元素,上一个集合权值和最小是多少。
我们发现转移只用枚举下一个集合是什么即可。注意需要取前缀 min 来优化,时间复杂度 。
但是这道题比较卡常,需要用刷表法,当遇到不可行的状态时就不去转移。
12.P2466 [SDOI2008] Sue 的小球
题意:
一个平面上有若干个小球从开始时刻以固定的速度开始下落,给定起点,从起点出发在 轴上移动,移动 1 格花费 秒。
每次第一次到达某个横坐标时,就能获得现在这个横坐标的所有小球的纵坐标的值的和,求收集完所有小球后贡献最大是多少。
。
思路:
首先,这道题最开始需要观察,我们发现,如果从起点出发,向左走了一段距离后向右走,那么我们肯定要走到越过原来起点的位置,这样才会有新的收益。所以我们就能大概知道答案的样子。
但是这个计算方式也需要转化一下,我们发现,当我们走了 秒后,我们对答案的贡献其实是当前没有走到过的小球的速度和。
所以任何时刻收集的小球都是区间,我们考虑区间 DP,设 表示走完 区间后,最后一次是 或者 。
如果直接枚举上一次不同方向的话就是 的了,过不去。我们发现其实 可以从 和 转移就够了,这样就能涵盖所有的情况。
所以我们便得到了 的做法。
13.CODE FESTIVAL 2017 qual B D-101 to 010
题意:
有一个 序列,每次可以将一个 变成 ,求最多能操作几次。
。
思路:
题解直接线性 dp 什么神仙。感觉我的做法更平易近人一点。
我们首先还是观察,我们发现其实我们可以将整个段按照中间隔了超过 1 个 0 的分成若干段,每一段都是 这样的。
我们先对于两个 0 的 ,我们发现让其中的一个 101 占用中间的所有 1 与两个都占一点是一样的。
所以我们可以根据这个对于每一段来 dp,设 表示第 个 占用左边的 1/右边的 1/不用。
转移非常简单,于是我们直接分段也是在 内解决这个问题。
14.ZOJ1234-Chopsticks
题意:
将 个数分成 个三元组 ,每个三元组权值是 ,求最小权值和。
。
思路:
首先不难猜测最优解的所有 都是相邻的,否则我们可以通过调整使得最优解不优。
所以我们就可以考虑 ,倒序排序,设 表示前 个选了 个的最小代价,如果 ,就用 转移即可。
注意这道题卡空间,需要滚动数组。
15.[ARC078F] Mole and Abandoned Mine
题意:
给定一张无向连通图,边有边权,求最少割掉的边权总和,使得 到 只有唯一一条简单路径。
。
思路:
的更劣做法。
我们首先需要观察最终剩下的样子,不难发现其实是将 划分成若干个集合,路径上每一个点都在一个集合中,集合之间除了路径上的边没有其他边。
这就很好 dp 了, 表示现在路径上最后一个点是 ,已经用了 中的点。
我们只需要枚举下一个路径上的店和其对应集合即可。需要预处理两个点集的所有边权,这个可以 暴力处理,但是更好的方法是算出一个点集内部的边权然后容斥,这样变成 。
于是总的复杂度是 ,可以用链表储存每个集合的元素,这样可以减少常数。
但是我们其实可以将选点和选集和分开,这样就是 的了。
16.CF55D Beautiful numbers
题意:
求 中所有被其每个位置上的非零数整除的数的个数。
。
思路:
最朴素的想法是记录当前存在的数字集合与 每个数字的余数,但是显然过不去。
首先,我们发现,只用知道 的余数就可以推出所有数是否整除,所以我们只用记录这四个书的余数。
其次,我们发现,我们其实只需要记录当前数字集合中 的最高次幂即可,所以我们总的状态数是 ,完全可做。
注意到是多测,所以我们记忆化搜索时不记录 lim 的记忆化。
17.Topcoder 修正表达式
题意:
现在有三个正整数 ,可以执行一下操作任意多次:
-
将 中的一个插入到某个数的某个位置,单次花费 元。
-
将某个数的某个位置修改,单次花费 元。
-
删除某个数的某个位置,单次花费 元。
现在给定 ,求使得 的最少花费,要求任意时刻都没有前导 。
思路:
我们考虑数位 dp,设 :
表示当前处理哪个数。
表示当前的 也就是进位。
分别表示当前应该处理到这三个数的哪一位。
表示当前三个数是否有前导 0。
表示当前执行的插入次数,以此来断绝后效性。
我们从 开始,然后 ,然后 轮流进行。
首先考虑终止状态,如果 (注意这个一定要有,否则有可能出现 这种最后一个 被忽略的情况)并且 并且 的话就是一个可能的终止状态。
否则,我们考虑转移。
首先,如果我们保留不变,则当前的 这个数处理减去 1,并且需要更新前导 和进位,同时要确保这个数不是前导 。
如果我们插入,我们枚举插入的这个数,依然要求没有前导 ,同时更新 ,
如果是修改,我们枚举修改成什么,然后更新即可。
如果是删除,需要注意,对于 ,我们可以直接 或 进行删除。但是假设当前我们还是前导 ,我们也可以不放数,不进行任何操作,转移到下一个数即可。
最后对于 的情况,如果存在某个时刻 ,则我们需要处理看看如果当前把 删了也是一种情况。
总之转移就是这些,代码用记忆化搜索还是相对比较好实现的。
18.CF1334F Strange Function
题意:
定义 表示 的前缀最大值构成的数组,给定 ,以及每个 中的数删除的代价,求最小代价使得 。
。
思路:
先考虑朴素的 dp,设 表示 的最小代价, 中位置 可以唯一确定。则:
我们考虑维护所有下标并 lazy 更新。
我们发现 时,如果 ,则比 大的都会更新,而本身还要考虑被 更新。
需要后缀加,单点查询,单点修改,用 BIT 维护即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效