Loading

dp 练习题 2024.2

dp 专场 *2。

CF1608F MEX Counting

题意:给出 \(n,m,b_{1...n}\),求出有多少个长度为 \(n\) 的序列 \(a\) 满足 \(\forall i\in[1,n],\space 0\le a_i\le n\)\(|\operatorname{mex} \{a_1,a_2,...,a_i\}-b_i|\le m\)

\(1\le n\le 2000,\space 1\le k\le 50\)

很简单的 dp,个人认为难度下位紫或更低(?)

考虑枚举 \(i=1,2,...,n\),依次填写 \(a_1,a_2,...,a_n\),并维护当前的 \(\operatorname{mex}\) 结果,不妨设为 \(j\)。当前填的数有三种:

  • \(<j\),并不会产生什么影响

  • \(=j\),此时当前的 \(\operatorname{mex}\) 会变大,变大多少取决于 \(j\) 后面一段已填过的数的个数。

  • \(>j\),这个数字可能对未来有影响,但我们目前未知

直接 dp,设 \(f[i,j,k]\) 表示填完前 \(i\) 个数,并且 \(\operatorname{mex}\) 结果为 \(j\),其中还有 \(k\) \(>j\)

考虑 \(a_i\) 的影响,如果 \(\operatorname{mex}\{a_1,a_2,...,a_{i-1}\}\) 还是 \(j\),那么 \(a_i<j\)\(a_i>j\),转移:

  • 如果 \(>j\) 的数字种类数不变:\(f[i,j,k]\gets f[i-1,j,k]\times(j+k)\)

  • 如果 \(>j\) 多了一个数字种类:\(f[i,j,k]\gets f[i-1,j,k-1]\times k\)

注意我们不计算这 \(k\) 种数的取值贡献,而是他们之间的相对大小顺序

接下来如果 \(\operatorname{mex}\{a_1,a_2,...,a_{i-1}\}<j\),不妨设为 \(x\),那么中间 \([x+1,j-1]\) 这一段一定都在前 \(i-1\) 个数出现过,我们不妨直接拿其中 \(>x\) 中的一些填入这 \((j-1)-(x+1)+1=j-x-1\) 个数中。由于我们已经考虑了相对大小顺序,直接拿最小的那几个填入即可。

  • 转移: \(f[i,j,k] \gets f[i-1,x,k+(j-x-1)]\)

总转移式

\[f[i,j,k]=f[i-1,j,k]\times (j+k)+f[i-1,j,k-1]\times k+\sum_x f[i-1,x,k+j-x-1] \]

\(j\) 个数为 \(O(m)\),前缀和优化即可做到 \(O(n^2m)\)

实现时注意细节问题。 记录


CF1450G

题意:一个小写字母组成的字符串 \(s\),其中字母 't', 'r', 'y', 'g', 'u', 'b' 不会出现,还给定了一个有理数 \(k=\frac ab\)

每次可以选择 \(s\) 中的一种字母,将 \(s\) 中所有的这种字母变成另一种字母,但有个条件:设这个字母出现了 \(c\) 次,需要覆盖这 \(c\) 个位置的最小区间为 \([l,r]\),那么需要满足 \(k\cdot (r-l+1)\le c\)

对于所有 \(s\) 中出现的字母,求出是否可以通过若干次操作使得 \(s\) 中全是这种字母。

\(1\le n\le 5000,\space 1\le a\le b\le 10^5\)

因为有 \(6\) 种字母不会出现,所以一共只有 \(20\) 种,可以考虑状压。

我们把字母分类,一类是一开始就不合法的,另一类是一开始合法的。

一开始已经合法的两种字母显然不需要合并,因此我们一开始需要将一种合法的字母合并到一种不合法的,然后产生一个新的状态。

如果还不合法则继续合并,直到这个字母合法,此时这是一个字母集合(合并的集合),然后把他作为一个新的合法“字母”继续合并。

\(f[S]\) 表示是否可以把 \(S\) 中的字母合并起来,并且合并出去。

  • \(S\) 中的字母分成两个合法集合,显然这两个集合可以分别合并出去,不需要额外合并起来:\(f[S\cup T]\gets f[S]\operatorname{and} f[T]\)

  • 合并到一个本来不合法的字母:\(f[S\cup \{x\}]\gets f[S]\)

时间 \(O(3^n)\),需要优化。

注意到如果两个集合 \(S_1,S_2(S_1\cap S_2=\emptyset)\) 对应的覆盖区间有交,且 \(S_1,S_2\) 都是合法的,那么 \(S_1\cup S_2\) 一定是合法的。

观察这能给我们什么思考,我们在第一种转移中枚举 \(T\),如果 \(S\)\(T\) 对应的覆盖区间有交且 \(f[S]=f[T]=1\),那么一定得到 \(f[S \cup T]=1\)

进一步的,钦定 \(S\)\(T\) 都是由若干个合法的集合合并到一个不合法的字母形成的,设这两个字母为 \(x,y\),设 \(S'=S\oplus \{x\}\),其实我们可以先把 \(T\)\(S'\) 合并,再转为 \(x\)。由于 \(S,S',T\) 都合法,如果去掉 \(x\)\(S',T\) 对应区间仍然有交,则 \(f[S'\cup T]=1\);如果无交,通过第一种转移也可以使得 \(f[S'\cup T]=1\)

对于 \(S,T\) 由多个集合合并起来的,可知每个集合都合法。拆分每个集合,如果可以找到一条分界线来分划这些集合对应区间显然合法;如果找不到,依次合并起来就好。

因此,第一种转移时,我们枚举的 \(S,T\) 额外保证 \(S,T\) 对应区间无交,即可优化。设 \(k\) 为字母种类数,时间 \(O(k2^k)\)记录


CF1621G Weighted Increasing Subsequences

题意:给出 \(n,a_{1...n}\),对于每个上升子序列 \(a_{i_1},a_{i_2},...,a_{i_m}\),子序列中 \(a_{i_j}\) 有贡献当且仅当存在 \(k\) 满足 \(k>i_m\)\(a_{i_j}<a_k\),求所有上升子序列的贡献和,模 \(10^9+7\)\(1\le n\le 2\times 10^5,\space 1\le a_i\le 10^9\)

考虑把 \(a\) 转化为一个排列 \(p\),相同的数则前面比后面大。不妨考虑 \(q=p^{-1}\)\(p\) 的上升子序列仍然对应 \(q\) 的上升子序列。对于一个上升子序列,设结尾位置为 \(x\),那么子序列中的一个位置 \(y\) 有贡献的条件是一个位置 \(z\) 满足 \(z>y\)\(q_z>q_x\)

我们只需要用总方案数减去不合法的即可,不合法的条件是不存在 \(z\) 满足 \(z>y\)\(q_z>q_x\),相当于 \(q_x\)\(q_{y...n}\) 的最大值。

我们对于每个位置 \(i\) 考虑其贡献,设 \(q_{i...n}\) 的最大值位置为 \(w\),我们要算的就是包含 \(i\) 且以 \(w\) 结尾的上升子序列个数,为 \(q_{1...i}\)\(i\) 结尾的上升子序列个数 \(\times q_{i...w}\)\(i\) 开头以 \(w\) 结尾的上升子序列个数。前半部分好做,注意 \(w\) 是由 \(i\) 更新的,不更新时直接维护,更新时只需要清空树状数组,时间 \(O(n\log n)\)记录


CF582D Number of Binominal Coefficients

题意:给出质数 \(p\) 和整数 \(\alpha,A\),求有多少对 \((n,k)\) 满足 \(0\le k\le n\le A\)\(p^\alpha| {n\choose k}\),答案模 \(10^9+7\)\(1\le p,\alpha\le 10^9,\space 0\le A\le 10^{1000}\)

Kummer 定理:\({a+b \choose a}\) 中质数 \(p\) 的次数为 \(a+b\)\(p\) 进制下进位次数。

感性证明:考虑对初始为 \(0\) 的数连续做 \(n\)\(+1\),在 \(p\) 进制下会进位 \(\lfloor \frac np \rfloor+\lfloor \frac n{p^2} \rfloor +...\) 次,这相当于 \(n!\)\(p\) 的次数。而 \({a+b \choose a}=\frac{(a+b)!}{a!b!}\),相当于连续 \(a+b\)\(+1\) 的贡献,然后去掉 \(a\)\(b\) 各自进位的贡献。

\(p\) 进制就可以直接数位 dp 了。

细节有点多,记录


CF1103D Professional layer

题意:给出 \(n,k,a_{1...n},e_{1...n}\),一次性修改 \(x\) 个数(\(x\) 自己定),对于每个修改的数 \(a_i\),选择 \(a_i\) 的一个约数 \(d\) 修改为 \(\frac{a_i}d\),使得最终 \(\gcd(a_1,a_2,...,a_n)=1\),求最小的 \(x\sum\limits_i e_i\)\(1\le n\le 10^6,\space 1\le k,a_i\le 10^{12},\space 1\le k\le 10^{12}\)

先求出 \(\gcd\),设为 \(g\)\(g\) 中质因子最多 \(10\) 个,设实际个数为 \(m\)

我们只关心 \(a_i\)\(g\) 中的质因子,求出每个质因子的次数。不难发现每个质因子次数都相同的两个数除了 \(e_i\) 是等价的,考虑分为若干个等价类,求出每个等价类的前 \(m\) 小的 \(e_i\) 分别是多少。

搜一下,等价类差不多一万多一些,比较少。

然后直接状压 dp,设 \(f[i,j,S]\) 表示前 \(i\) 个等价类处理的质因子集合为 \(S\),修改了 \(j\) 个数,最小代价是多少,直接转移即可,时间 \(O(\text{可过})\)记录

CF1784E Infinite Game

题意:一个由 a 和 b 构成的字符串 \(s\),长度为 \(n\)。两个人 Alice 和 Bob 在玩游戏,第 \(i\) 场中如果 \(s_{(i-1)\bmod n+1}\) 为 a 则 Alice 赢,否则 Bob 赢。两人遵循三局两胜原则:每当一个人胜场满两场时,称那个人赢了一轮,然后清空胜场记录开始新的一轮。设 \(w_i\) 为前 \(i\) 轮中 Alice 赢的轮数,当 \(i\to \infty\) 时若 \(\frac {a_i}i>\frac 12\) 则 Alice 是赢家,若 \(\frac {a_i}i =\frac 12\) 则两人平局,若 \(\frac {a_i}i<\frac 12\) 则 Bob 是赢家。现在 \(s\) 中挖了一些空,求所有可能的 \(s\) 中 Alice 赢、两人平局、Bob 赢的方案数分别是多少,模 \(998244353\)\(1\le n\le 200\)

确定 \(s\) 后,设有 \(n\) 个点 \(0,1,2,...,n\),每个点表示当前轮结束后的位置,每个点向下一轮结束的点连有向边,不难发现这些点形成基环树,所以游戏一直无限进行下去时,一定是一直在环上绕。

Alice 赢的条件是环上 Alice 赢的轮数比 Bob 多,Bob 赢的条件是 Bob 赢的轮数比 Alice 多,平局的条件是一样多。

每次经过 \(0\) 时可能不是完整一轮,有 \(4\) 种状态(每人可能得 \(0/1\) 分)。考虑每个状态扫过一个 \(s\) 后的得到的状态,这些状态形成基环树,找到这个环即可。

现在需要知道谁赢,可以考虑记下环上的状态的 Alice 赢的轮数 - Bob 赢的轮数总和,计入状态,但问题是我们根本不知道哪些状态在环上。可以一开始先暴力枚举是哪些状态,然后 dp,最后计算时判断一下。

时间复杂度 \(O(n^2)\),常数为 \(2^4\times 4^4\),可过。

记录


CF1842H Tenzing and Random Real Numbers

题意:有 \(n\) 个变量 \(x_{1...n}\),在 \([0,1]\) 中随机取值。有 \(m\) 条限制,每条形如 \(x_i+x_j\ge 1\) 或者 \(x_i+x_j\le 1\),求满足所有限制的概率。 \(1\le n\le 20\)

考虑 \(x_i+x_j\ge 1\) 转化为 \(\frac{x_i+x_j}2 \ge 0.5\),这样相当于对一对变量的平均值限制为 \(\le 0.5\)\(\ge 0.5\)

考虑一开始有一条 \(0.5\) 的分隔线,我们按照与 \(0.5\) 差的绝对值从小到大加入变量,每次可以加在最上面或者最下面。

\(f[S]\) 表示加入的变量集合为 \(S\) 的合法概率。加入 \(x_i\) 在上面时,不难发现 \(x_i\)\(S\) 中每一个变量的平均值都 \(\ge 0.5\),判断一下即可。

然后每个变量在上面和在下面概率为 \(\frac 12\),这些变量与 \(0.5\) 的差的绝对值的每一种可能的大小顺序概率为 \(\frac 1{n!}\),乘上就行,\(O(n2^n)\)

记录


CF1874E Jellyfish and Hack

题意:一个排列 \(P\),定义 \(w(P)\): 我们把 \(P_{2...n}\)\(P_1\) 为根据分成 \(<P_1\)\(>P_2\) 且相对顺序不变的两个序列 \(L,R\),然后 \(w(P)=|P|+w(L)+w(R)\)

求出多少种长度为 \(n\)\(w(P)\ge lim\) 的排列 \(P\),模 \(10^9+7\)\(1\le n\le 200,\space 1\le lim\le 10^9\)

\(lim\) 过大没有用。容斥,改为求 \(w(P)<lim\)

一个显然的 DP:设 \(f[i,j]\) 表示有多少个长度 \(i\) 的排列,且其 \(w\) 值为 \(j\)

\[f[i,j]=\sum_{k=1}^i \sum_{l=0}^j f[k-1,l]\cdot f[i-k,j-l] \]

卷积,设 \(F_i(x)=\sum\limits_j f[i,j]x^j\)

那么

\[F_i(x)=\sum_{k=1}^i F_{k-1}(x)*F_{i-k}(x) \]

接下来很妙的一步,考虑带入 \(x\),拉插插出多项式 \(F_n(x)\)

可知次数为 \(k=\frac{n(n+1)}2\),带入 \(k+1\) 个不同的 \(x\),为 \(x=1,2,...,k+1\)

然后我们可以把卷积改成点乘,dp 是 \(O(n^4)\) 的。

然后拉插插出多项式,有 \(k+1\) 个点值。对于第 \(i\) 个,分母是容易算的,分子是 \(\frac{\prod_{j=1}^n x-x_j}{x-x_i}\),上面部分预处理,下面直接暴力除。

时间复杂度 \(O(n^4)\)

记录


CF1804H Code Lock

题意:有一串密码,长度为 \(n\),由前 \(k\) 个小写字母组成。有一个密码盘,输入密码时,每秒可以

  • 输入一个小写字母

  • 将箭头往左移一格

  • 将箭头往右移一格

请设计这个密码盘(包括初始箭头指向),使得输入密码的秒数最小,求出这个数,以及有多少种设计方案。 \(1\le k\le 16,\space 1\le n\le 10^5\)

首先对于密码串,我们可以只保留 \(cnt_{i,j}\) 表示字母 \(i,j\) 出现相邻的次数。这样,密码盘的代价就是 \(\sum\limits_i\sum\limits _j \text{dist}(i,j)\times cnt_{i,j}\),其中 \(\text{dist}(i,j)\) 是两个字母之间的最小移动次数。

关键问题是他是一个环,两个字母之间有两种移动方式,我们难以判断是顺时针移动还是逆时针移动。

\(p_i\) 表示字母 \(i\) 的位置,那么 \(i,j\) 之间的距离就是 \(\min(|p_i-p_j|,p_i+n-p_j,p_j+n-p_i)\)

我们很容易想到需要把式子拆掉,然后两个字母分开贡献。但是仍然无法处理 \(\min\) 和绝对值的问题。

先考虑 \(k\) 为偶数的情况。仔细思考,两种移动方式的距离的分割线是 \(\frac k2\),考虑折半的方法,我们可以在 \(k\) 中间砍一刀,然后左边和右边同时从前往后填字母。这样一来,不难发现,填写字母时,我们很容易知道他对于哪些段的贡献是怎样的。

如上图,\(S,T\) 是已经填写的字母集合,而 \(S',T'\) 未填写。当我们给 \(S'\) 最前面的位置(\(S\) 的后一个位置)填写一个字母 \(x\) 时,不难发现对于 \(S'\)\(T\) 中字母,\(x\) 与他们的移动距离就是位置相减,其中 \(p_x\) 的贡献应是减去,系数为 \(\sum\limits_{y\in \{S' \cup T\}}cnt_{x,y}\)。同理,对于 \(S,T'\) 贡献应是加上。

为了知道 \(S',T'\) 中分别是哪些字母,我们需要提前枚举左边和右边的字母集合。

转移考虑枚举 \(S,T\) 后分别填写字母 \(x,y\),然后计算各自的贡献。

这样的转移是 \(O(k^2)\) 的。由于 \(x,y\) 之间两条路径长度是一样的,考虑让 \(x\) 归为 \(S'\),让 \(y\) 归为 \(T'\) 来计算。为了避免需要额外计算 \(x,y\) 之间的贡献,我们转移可以考虑拆开枚举:先枚举 \(y\) 来从前面转移过来,再枚举 \(x\) 把当前转移到后面,这样可以做到 \(O(k)\) 转移。

最后考虑 \(k\) 为奇数的情况。我们让左边部分后面多一个字母,容易处理,可以发现正确性也是对的。

时间卡一卡就能过了。

记录

posted @ 2024-02-26 11:05  Lgx_Q  阅读(24)  评论(0编辑  收藏  举报