DP套DP

有些时候,对于某一个数列(或者串等其他东西),我们可以使用DP判断其是否合法。
于是有毒瘤人们就会想到一种题目,对于这种需要用DP来判断是否合法的东西,能不能对其进行计数呢?

对于有些是可以的。

我们考虑一下:因为DP本来就是一个有限状态自动机,也就意味着转移和状态数都是固定的,如果我们把状态通过编号或者状压压到一维,我们就可以处理了。而方案数统计本来就是一个DP,所以这种神奇的方法就叫做DP套DP

DP套DP大概就这么多,还是要上题:

[TJOI2018]游园会

给定长度 N 和由N,O,I组成的串 S。问有多少个长为 N,且由N,O,I组成的串与 S 的最长公共子序列的长度为 m ,且串中不含NOI的串的个数。
输出对于 m=0,1|S| 的答案。
我们考虑如何检验一个串 T 的与 S 的最长公共子序列长度和是否含有串 NOI
对于前者,我们的朴素想法是维护 fi,j 表示串 T 的前 i 位和串 S 的前 j 位的最长公共子序列。
对于后者,我们会选择跑KMP,但由于匹配串NOI长为3且字母互不相同,其实就是N,O,I这三个字符之间的转移,有些可行有些不可行。
后者很容易被压在 0,1,2 中,我们就需要考虑前者如何处理。
我们再来看一下前者的转移,fi,j={max(fi1,j,fi,j1)TiSjmax(fi1,j,fi,j1,fi1,ji+1)Ti=Sj
通过数学归纳或者感性理解,我们会发现:fi,jfi,j11 ,这也就意味着,我们其实可以用一个长度为 |S| 的二进制数来表示一行的转移。
我们只需要处理出来 2|S| 种情况分别对于 T 下一位为N,O,I的转移即可。
我们外层的DP就是 Fi,S,j 表示处理到了第 i 为,最长公共子序列的匹配为 S ,与NOI匹配到了第 j 位时的方案数。
总体复杂度 O(n2|S|)

CF979E Kuro and Topological Parity

还没有写捏

[ZJOI2019]麻将

upd on 2024.02.28

没想到会有时间补这个,很厉害。

对于我们手上拿到的牌,记 ai 为我们拿到的大小为 i 的牌的数量,我们考虑如何判断一副牌是否满足条件。也就是我们想要建立一个自动机,把 {an} 逐位扔进去就可以得到结果。

dpi,j,k,0/1 表示,处理到了大小 i 的所有牌,预留了 ji1i 作为 i1,i,i+1 的顺子,ki 作为 i,i+1,i+2 的顺子,有没有对子的情况下,最多有多少个面子。如果任何时刻某一个状态的 dpi,j,k,0/14 了,就说明这副牌胡了。显然有 j,k<3,否则可以将其拆成刻子。

考虑转移,我们加入了 ai+1i+1,考虑 dpi+1,k,l,0/1dpi,j,k,0/1,显然有 ai+1j+k+l,所以可以组成 ai+1jkl3 个刻子,如果我们要留下一组对子就用 ai+12 转移即可。

考虑到胡牌还有可能是七小对,所以我们在单独维护一个有多少个 ai2

这样我们可以存储 dp0/1,i,j 以及一个 paircnt 来维护一个状态,我们使用 bfs 对其建自动机,发现只有 M=2092 种状态。

然后用 dpi,j,S 表示处理了大小 i,一共有 j 张牌,状态为 S 的方案数。

那么最终会答案就等于 1+t=14n13F(t),其中 F(t) 为摸 t 张牌没有胡的方案。

时间复杂度是 O(Mn2) 的。

[NOI2022]移除石子

神秘思维题,详见Alex_Wei老师因为我也是在他的博客里学的
我们一层一层的来思考:
第一步、考虑如何检验某种石子情况是可行的的。
不难发现选择长度 3 一个区间,相当于选择若干次长度 =3,4,5 的区间;同时存在一种方案不会选择同一个区间 2 次。这两件事情告诉我们,我们从每一个位置开始的区间数会 3 个。
所以我们就可以考虑维护 fi,j,k,l 表示,i 之前的位都已经处理了,现在有 j 个可以选择延伸到第 i 位,有 k 个必须延伸到第 i 位,有 l 个必须延伸到第 i+1 位。
我们假设可以延伸的我们选择了 p[0,j] 个,在满足 ai=p+k+laip+k+l+2 的情况下,我们得到转移 fi,j,k,lfi,p+k,l,st,st[0,3],最终检查 fn+1,,0,0 是否存在即可。
我们考虑两个优化:如果我们同时在第 i 位开启了一个 45,我们可以把它变成 i+1 位的 34,也就意味着我们可以不同时取 3,4,5,所以 j,k,l2;我们可以钦定有哪些会延伸到第 i 位,也就是枚举 p[k,j+k] ,这样我们维护的DP就变成了 fi,j,k 其中 j4,k2 了。
据Wei老师做写,我们可以枚举验证第二位 j 也是可以降到 j2 的。

第二步、转化恰好 k 的这个条件。
在这种问题里,恰好一定是比至多难做的,所以考虑能不能转换一下。
k=0 时,等价于我们上面的转移。
k=1 时,如果有一次操作1,则必然可行;只要有一次长度大于 4 的操作2,则必然可行;只要 n>3 且有一次长度大于 3 的操作2,则必然可行。
对于上述情况的方面,我们会发现只有两种,第一种是 ai=0,i=1,2n,第二种是 n=3a1=a2=a3=1
k=2 时,对于 k=0 时可行的,k=2 一定可行,对于 k=1 可行的,我们发现不可能出现 k=1 时将有解变无解的情况,(因为你根本不可能在上面的两种情况中删掉石子还保证有解),我们可以重复一次 k=1 来达到 k=2 的效果。
同理,我们便得到,当 k>1 时,放恰好 k 合法的方案数,等价于放 k 个石子合法的方案数。

第三步、考虑得到某种石子情况至少需要加入多少个石子。
我们模仿第一步,维护 gi,j,k 表示 i 之前的位都已经处理了,有 j 要延伸到第 i 位,k 个延伸到第 i+1 位,至少需要加多少个石子。
假设 i 位有 ai 个石子,记 v=aipjk ,其中 p{0,1,2} 表示我们在第 i 位新开的区间数。
如果 v<0 我们显然至少需要 v 个石子,如果 v=1 ,由于不能进行操作1,我们需要 1 个石子,其他情况不需要石子,所以得到转移 gi,j,k+nedgi,st,p,st[k,k+j]

第四步、考虑外层DP 时 ai 的影响。
由于 p+j+k 范围较小,同时根据对拍或达标,我们会发现,对于 ai6 的情况时等价的。
所以有意义的转移只会有 ai=0,1,2,3,4,5ai67 种。
我们DP套DP的雏形已经出来的,但由于 k100 ,也就意味这每一个 g 的取值是 [0,101] ,似乎有 1029 种状态。

第五步、保留有用的内层DP。
我们感性理解,发现 g 的值应该不会差的太远,所以有用的 g 的组合应该是有限的。
所以我们考虑暴力维护一边所有的转移,可以发现有效的转移数是 S=8765 种。
预处理出来所有转移,DP即可,最终复杂度 O(TnS)

posted @   Xun_Xiaoyao  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
/* 鼠标点击求赞文字特效 */
点击右上角即可分享
微信分享提示