部分 dp 做题记录

记录了一些可能有价值的 dp ,当然大部分都是当时小蒟蒻不会做的(

AGC046 C

给出一个 01 串 \(S\) ,每次可以选择一对二元组 \((i,j)\) 满足 \(i<j\) 且第 \(i\) 位为 \(0\)\(j\) 位为 \(1\) ,然后将第 \(j\) 位的 \(1\) 移到第 \(i\) 位的前一位,求进行不多于 \(K\) 次操作得到的不同的字符串个数是多少。

\(|S|\le 300 , K\le 10^9\)

就当是开胃小菜吧(

每次都是把一个 \(1\) 移到 \(0\) 的前面,显然对于某个可得到的字符串可以在不超过 \(|S|\) 次操作得到,所以 \(K\) 可以和 \(n\)\(min\)

根据操作,可以按照 \(0\) 将串分段,然后搞个 \(dp_{i,j,k}\) 分别记录前 \(i\) 段一共有 \(j\)\(1\) 至少做了 \(k\) 次操作得到的不同字符串个数,转移枚举这一段有多少个 \(1\) ,可以用前缀和优化做到 \(\mathcal{O(n^3)}\)

AGC046 D

给出一个 01 串 \(S\) ,每次可以将最前面的两个字符拿出,删除一个,将另外一个插入字符串的任意一个地方,问能得到多少种不同的字符串。

\(|S|\le 300\)

ARC110 E

给出一串只包含 \(A,B,C\) 的字符串 \(S\) ,每次可以选择一个 \(i\) 满足 \(S_i\not=S_{i+1}\) ,然后将 \(S_i\) 变为与这两个字符都不同的另一个字符,删除 \(S_{i+1}\) ,问通过数次操作能得到多少种字符串。

\(|S|\le 10^6\)

主要是转化,可以将 $A,B,C$ 看作 $1,2,3$ ,那么一次操作就相当于将 $S_i,S_{i+1}$ 变为 $S_i\ xor\ S_{i+1}$ ,可以发现,如果一个区间的异或值不为 $0$ ,且包含不止一种数,那么就一定有方法将这段区间变为区间的异或值。

很显然有可以设 \(dp_i\) 为前 \(i\) 位可以搞出多少种字符串,暴力的转移是找到一个 \(j\) 使得 \(S_{[j+1,i]}\) 满足上面的条件,然后求和,注意到这个条件主要和异或和有关,那么可以在转移时对于每种异或值维护所有满足的 \(j\)\(dp_j\) 的和,而异或值只有 \(3\) 种,至于第二个条件随便搞搞就行。

AGC051 D

给出 \(a,b,c,d\) ,分别代表对应边的经过次数,问从 \(S\) 出发回到 \(S\) 且满足每条边的经过次数的路径有多少条。

\(n\le 50\ 000\)

bzoj3864

给一个长度为 \(m\) 的字符串 \(T\) ,对于每个 \(i\) ,求出有多少个长度为 \(n\) 的字符串 \(S\) ,满足 \(LCS(S,T) = i\) ,模 \(10^9+7\)\(LCS\) 指最长公共子序列。

\(n \le 1000, m \le 15\),字符集大小为 \(4\)

经典的 dp 套 dp 。

假如已知字符串 \(S\) ,求 \(LCS(S,T)\) ,有 \(dp_{i,j}\) 代表 \(S\) 的前 \(i\) 位和 \(T\) 的前 \(j\) 位的 \(LCS\) ,显然有 \(dp_{i,j+1}\le dp_{i,j}+1\) ,那就意味着 \(dp_{i}\) 的差分数组是一个 01 串,可以试着状态压缩。

posted @ 2021-02-21 08:46  Dabuliuzp  阅读(0)  评论(0编辑  收藏  举报
/* */ 返回顶端