dp 题记录

CF1716D Chip Move

给定两个数 n,k,问从 0 开始,第 i 步只能走 (k+i1) 的倍数,问分别走到 x[1,n] 的方案数,对 998244353 取模。


考虑 dp,设 dpi,j 表示当前在 i,走了 j 步的方案数。

dpi,jdpi+x,j+1

初值为 dp1,0=1,暴力转移复杂度为 n2n

其中 x(k+j1) 的倍数,额,肯定是外层循环枚举走到了第 j 步,然后那么 kj+1 是已知的。

考虑一个数在这种情况下会加上哪些数,维护一个前缀和应该就好了?

你这个看上去,就不能走太多步的样子啊其实。

因为 k+(k+1)+(k+2)++(k+m)n 这个 m 始终小于等于 n,那么就可以根据这个做了。

首先滚动数组,之后我们每次维护一个魔改的前缀和就好了。

CF1701E Text Editor

给定两个字符串 S,T,初始时光标在串 T 尾部,你可以进行以下操作:

  • left:将光标向左移动一个字符,如光标在字符串最左侧则不移动。

  • right:将光标向右移动一个字符,如光标在字符串最右侧则不移动。

  • home:将光标移动到字符串最左侧,如光标在字符串最左侧则不移动。

  • end:将光标移动到字符串最右侧,如光标在字符串最右侧则不移动。

  • backspace:将光标左侧的第一个字符从字符创中删除,如光标在字符串最左侧则不删除任何字符。

我们需要使 S 在做若干次操作后得到 T,请你求出最小的操作次数。无解输出 1


我草,不会啊,爬去看题解。

直观感受的话你肯定是用 leftbackspace 或者在中间某个时刻突然 home 然后 rightbackspace

那么,我们从前面和后面分别跑一遍 dp,然后枚举一个中间端点取答案的 min 就好了。

跑的 dp 形如 dpi,j 表示当前光标到了 s 的第 i 位,目前和 t1j 位匹配。

然后 dpi,j=dpi1,j+2 是表示删除

然后 si=sj 就可以不用删除,dpi,j=dpi1,j1+1

然后记录 fpi,j 表示 s1it1j 匹配的最小值。

si=sj 的时候且不用删除小于删除,那么 fpi,j=fpi1,j1,就考虑不移动,否则 fpi,j=fpi1,j+2

倒着过来的时候删除是 +1 的。

然后最后前面和后面做一个匹配,一下就好了。

[HNOI2014]米特运输

一棵树,每个点有权值,要求修改点权值满足,每个点是儿子权值的和,同一个点的儿子权值相同。

要求最少的修改次数。


首先容易想到 n2,然后发现确定了一个点的值就确定了所有点的值。

设当前节点的值为 x,那么此时根节点权值为 fasizfa×x,其中前面的连乘符号表示的是祖先的 siz 连乘。

那么我们记录下这个状态,然后取最多的为同一个数的就好了,因为这样修改的就最少。

这个部分的话,可以哈希,也可以取对数来求。

取对数的时候注意不能用桶判断相同,要手写 eps。

牛客小白月赛 53 F

n 个长度为 m 的二进制数,要求选出里面的一个子序列,满足每一位没有重复的 1 出现,求有多少种子序列的方案数


我们很容易想到一个复杂度为 n×2m 的一个 dp,是 dpi,j 表示考虑了前 i 个,以 j 结尾的满足要求的子序列方案数。

那么每次转移的时候也就是 dpi,ai+=k&ai=0dpi1,k,这里做的复杂度就是 n2m,然后同时每次还要继承一下上一次的状态,滚动数组一下就好了。

但是不能过,这里有一种降低复杂度的神奇方法。

我们默认这里的 m 为最大的 16,令 gi,j,k 表示考虑了前 i 个数,结尾的数的高 8 位为 j,低 8 位和 k 按位与后为 0 的子序列的方案数。

对于一个数可以 x=(ai>>8),y=(aimod255) 可以得到高位和低位。

那么我们首先模拟一遍 k 为高八位,然后如果 k&x=0 那么让 gi,x,ygi1,k,y,因为此时 gi1,k,y 表示 k 多对应 的那个低位也和 y 按位与为 0,那么就有贡献。

设这部分的总贡献为 res

然后模拟一遍 k 为低八位,然后如果 k&y=0,那么我们现在对应的状态其实就是 gi,x,k ,那么我们此时对应的操作就是 gi,x,kres

第三维度从来指的都不是低 8 位,而是低八位 & 上他为 0

然后显然第一维其实是没有什么用的,于是我们就可以把他滚动掉。

这道题挺厉害的感觉。

Luogu P1272 重建道路

一颗 n 个点的树,然后要求删边,问,删边使得剩出一个大小为 p 的连通块要用的最小删边数量。


dpi,j 表示当前在子树 i,保留下一个含有他的大小为 j 的连通块最少要用的一个删边数。

初始化 dpx,1=0,啥也不管,然后考虑往下接儿子。

你发现这,其实就是一个树形背包,就直接每次从儿子转移过来的时候,考虑 dpx,j=min{dpx,j+1,dpx,jk+dpto,k} 就好了,然后这里一个要注意的点是,里面那个 +1 一定要在每次循环枚举 k 之前就加了!

虽然我也不知道为什么会错,但是好像挺奇怪的,我思考了一下也不知道为什么。

复杂度树形背包写的正确的话就是 O(np) 的,我也不知道为啥 n150

CF873D Round Subset

不写题意了以后/难过。

注意到末尾 0 的个数之和 2,5 的个数有关,于是考虑状态 dpi,j,a,b 表示前 i 个选了 j 个,有 a2b5 的时候是否合法。

空间不太行,所以压一下 dpi,j,a 表示前 i 个选了 j 个有 a5 时最大的 2 的个数,同时第一维可以滚动掉,直接转移即可。

CF1710C-XOR Triangle

这题不会啊,感觉数位 dp 还是要重学一下。

容斥考虑不合法的三元组,然后用全部的三元组数目 (n+1)3 减去不合法的数目就可以得到合法数目。

x=ab,y=bc,z=ac,则有 xyz=0

x+zy,x+yz,y+zx 是违法的判定条件

x+yz 等价于 x,y 的二进制对中没有 11z 中没有 0000 除外)

x+zy 等价于 x,z 的二进制对中没有 11y 中没有 0000 除外)

y+zx 等价于 y,z 的二进制对中没有 11x 中没有 0000 除外)

可以设 dpi,s1,s2 表示还有 i 位没考虑,a,b,c 是否等于 nx,y,z 是否全 1(或 000),这个状态下的不合法数目。

s1 用三个位表示前三个状态,s2 用三个位表示后三个状态、

初始 dpn,7,7=1,因为此时只有一种情况 a=b=c=0

枚举 a,b,c 当前位的选取情况,假设是 s,则 dpi+1,s1,s2dpi 的贡献如下:

如果 n 当前位为 0,只能转移到 s1next=s1,此时要保证 s1&s=0, 不然说明有等于 n 前缀且当前选择 1 的情况,这样就大于 n 了。

如果 n 的当前位为 1,则能转移到 s1next=s1&s,计算出 s2next 要通过前面的状态 s2s 计算。

P3713 [BJOI2017]机动训练

转换一下题意,题目中的机动路径假如有 sum 个,那么贡献 sum2,用组合意义转化一下,这个等价于两个人走同样的机动路径的方案数。

注意到,每个点移动的方向只会有一种,要么是左上,左下,右上,右下(类型一),要么是正上,正下,正左,正右(类型二)。

题目要求路径不能远离目标点,那么移动的方向一定是确定的,可以枚举方向。

所以可以设 dpa,b,c,d 表示第一个人从 (a,b) 出发和第二个人从 (c,d) 出发,走的机动路径相同,沿着当前的方向走的合法方案数。

然后每次枚举方向,然后搜出能走的选择,在直接记忆化搜索路径,然后就可以求得答案,注意到,我们的正上,正下之类的,会被类型一给包含。

例如:正上的抉择被左上和右上能走的方向中包含,算了两次,于是容斥一下,对于类型一的答案全部加上,对于类型二的答案全部减去就好了。

P5307 [COCI2018-2019#6] Mobitel

卡老师题

首先傻逼 dp,直接设 dpi,j,k 表示走到 (i,j) 乘积为 k 的方案数,但是空间太大了,完全寄。

考虑将状态进行另一种转化,我们并不关心具体的值,而是关心一个相对的大小关系,也就是 × 多少会比 n 大,设 dpi,j,k 表示走到 (i,j) 时,当前乘积 ×k 之后比 n 大的方案数。

本质不同的 k 的数量等价于是一个整除分块,于是只会有根号种,第一位滚动一下数组,可以开下空间。

然后刷表更新即可。

posted @   Pitiless0514  阅读(52)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示