省选 dp 专题 1 做题记录

省选 dp 专题 1 做题记录

A CF1342F Make It Ascending

\(\text{Link}\)

由于 \(n\le 15\),显然考虑状压 dp。一个简单的状态是设 \(dp(i,S,j)\) 表示上一组所有数字加在 \(i\) 处,所用数字状态为 \(S\),且该组和为 \(j\) 的最多组数。显然组数越多越优。每次枚举 \(S\) 的补集的子集,找出子集中第一个大于 \(i\) 的位置作为下一组的基准位置,显然这样尽可能靠前选更优。用 __builtin_ctz 可以将这一部分复杂度降到 \(O(1)\)

不过这样有一个问题是 \(j\) 比较大,枚举的复杂度太高。此时需要用到一个 trick:值域定义域交换,即 \(j\) 存储的是当前的组数,而 \(dp(i,S,j)\) 存储的是当前状态下最后一组和的最小值,显然这个值越小越优。这样的话我们的复杂度就降到了 \(O(3^n n^2)\),足以通过本题。输出最优方案只需要简单记录转移点即可。

B CF1239E Turtle

\(\text{Link}\)

省选图论专题 1 做题记录 - B CF1239E

C P6806/CF1403C [CEOI2020] 象棋世界/Chess Rush

\(\text{Luogu Link}\)

\(\text{CF Link}\)

拼好题,把 \(5\) 个部分都做一遍就行。

  • \(\text P\)

    如果 \(c_1=c_R\) 则可以走到,步数 \(n-1\),方案只有一种;否则无解。

  • \(\text R\)

    如果 \(c_1=c_R\) 则一步走到,否则两步走到。方案只有一种。

  • \(\text{Q}\)

    如果在同一条斜线上则一步走到,方案为 \(1\);否则,有以下四种走法:斜-纵、横-斜、斜-斜、横-纵,步数均为两步,按照棋盘范围判断能不能这样走即可。注意每种走法实际有两种顺序,所以最后要乘 \(2\)

前面三种情况都是 trivial 的,后面两个比较难一点。

  • \(\text B\)

    先判断一下是否有解,看 \(n-c_R+c_1\) 奇偶性即可。

    首先象的最优策略就是不断撞墙然后反弹出去,直到最后一步可以直接走到就停止,于是步数我们可以直接求出。接下来要进行计数,直接算比较困难,考虑先弱化条件,我们不考虑最后一步可以直接走到,就一直按照撞墙反弹的路线走,然后记第一次走到终点正上方的某个格子为 \((x,y)\)

    如此我们需要将终点向下挪动 \(y-n\) 格,考虑怎样才能挪动终点,实际上就是我们每个拐点可以不撞墙,而是选择向内缩,每有一个拐点向内缩一格终点就会下降两格。所以令 \(d=\tfrac{y-n}{2}\)\(t\) 为拐点个数,根据经典插板法结论,这个的方案数就是:

    \[\binom{t+d-1}{t-1} \]

    但是 \(t-1\) 的大小是 \(O(n)\) 级的,复杂度无法接受。显然我们可以把 \(t-1\) 换成 \(d\),这样暴力求解组合数的复杂度就是 \(O(m)\) 的了。

  • \(\text K\)

    这一部分是最难的部分。首先发现王走的步数一定是 \(n-1\),这就告诉我们王的决策只有上、左上、右上三种。于是设 \(dp(i,j)\) 表示王走到 \((i,j)\) 的方案数,就有一个简单的 dp 方程:

    \[dp(i,j)= \begin{cases} dp(i-1,j-1)+dp(i-1,j)+dp(i-1,j+1)&1<j<m\\ dp(i-1,j-1)+dp(i-1,j)&j=m\\ dp(i-1,j)+dp(i-1,j+1)&j=1 \end{cases} \]

    直接矩阵快速幂就可以做到 \(O(m^3\log n)\) 预处理转移矩阵,然后每次询问就是 \(O(1)\) 的。不过这个复杂度还是太高,观察到瓶颈在于矩阵乘法,所以考虑对其进行优化。

    令单次转移矩阵为 \(A\),则矩阵快速幂的操作可以看作只有 \(\times A\) 和求二次方。前者容易优化,因为 \(A\) 有值的位置只有 \(O(m)\) 个,只考虑它们即可,复杂度可以做到 \(O(m^2)\)。然后是后面一部分,这里需要我们观察出 \(A\) 矩阵的一些性质:

    • \(A_{i,j}^n =A_{j,i}^n\)\(A_{i,j}^n=A_{m-j+1,m-i+1}^n\)。这告诉我们 \(A^n\) 永远是关于两条对角线对称的,证明显然,因为 \(A\) 本身就满足这个性质。

    • \(A_{i,j}^n=A_{i-1,j-1}^n+A_{1,i+j-1}^n(i+j-1\le m)\)

      这个性质比较难看出,可以认为它建立了一个矩阵元素间的递推关系。

      考虑证明,采用归纳法,首先 \(j=1\) 显然成立,考虑从 \(j\to j+1\) 的过程。首先根据性质 \(1\) 可知 \(A_{i,j}^n=A_{j,i}^n\)。所以有:

      \[A_{i,j}^{n+1}=A_{j,i}^{n+1}\Rightarrow A_{i,j-1}^n+A_{i,j}^n+A_{i,j+1}^n=A_{j,i-1}^n+A_{j,i}^n+A_{j,i+1}^n \]

      消掉 \(A_{i,j}^n\)\(A_{j,i}^n\) 并移项可得 \(A_{i,j+1}^n=A_{j,i-1}^n+A_{j,i+1}^n-A_{i,j-1}^n=A_{i-1,j}^n+A_{i+1,j}^n-A_{i,j-1}^n\)。由于对于 \(j\) 来说 \(A_{i,j}^n=A_{i-1,j-1}^n+A_{1,i+j-1}^n\) 成立,所以将 \(A_{i+1,j}^n\) 换掉可得:

      \[A_{i,j+1}^n=A_{i-1,j}^n+A_{i+1,j}^n-A_{i,j-1}^n=A_{i-1,j}^n+A_{i,j-1}^n+A_{1,i+j}^n-A_{i,j-1}^n=A_{i-1,j}^n+A_{1,i+j}^n \]

      于是我们就证明了这个结论。

    根据这些性质我们发现,只要知道了这个矩阵的第一行就能递推求出下面的元素,所以第二部分的复杂度也可以优化到 \(O(m^2)\)。所以预处理转移矩阵的复杂度就是 \(O(m^2\log n)\) 的了。

综上,我们就可以在 \(O(m^2\log n +qm)\) 的复杂度内解决这个问题。

D CF613E Puzzle Lover

\(\text{Link}\)

我们发现由于网格是 \(2\times n\) 的,所以走出的路径应该有三部分:左边的 U 字形,中间的路径和右边的 U 字形。为了方便统计我们先强制钦定中间的路径是向右走的,这样只需要反转一下字符串再跑一遍就能得出答案。

先处理两边的 U 字形,对于左边的 U 字形来说,实际上只需要求出 U 字形终点为该点时能否匹配到字符串的第 \(i\) 位,记其为 \(bg_{x,y,i}\)。这个可以很容易的用哈希 \(O(n^2)\) 求出。对于右边同理,求出当前匹配到第 \(i\) 位时能否匹配完整个字符串,记其为 \(ed_{x,y,i}\)

然后考虑中间的部分,这里就可以用 dp 求解了。令 \(f(x,y,i)\) 表示走到 \((x,y)\) 且上一步是向右走,匹配到字符串第 \(i\) 位的方案数;\(g(x,y,i)\) 同理,但是上一步是向上或向下走。转移是非常容易的,复杂度 \(O(nk)\)

在 dp 赋初值的时候用 \(bg\) 赋初值,然后最后求答案的时候再用 \(ed\) 判断能否匹配完即可,注意这里只能用 \(f\) 来匹配最后的 U 字形,用 \(g\) 是错误的。如此就可以在 \(O(n(n+k))\) 的复杂度内求出答案。

最后我们还需要注意去重,当起点和终点在同一列的时候这条路径实际上是被我们正反统计了两遍的,所以需要将这一部分的方案减掉;同时还需要注意一下串长为 \(1,2\) 的情况。反正就是细节巨大多。

E CF1466H Finding satisfactory solutions

\(\text{Link}\)

首先题目中给出的条件有这样一句话:\(\forall i\in S,a_i'\in S\)。也就是说选出的这些 \(i\)\(a_i'\) 应该构成一个循环置换。看到循环置换就应该能想到建图判环。同时为了满足有更优解这个条件,我们连的边也应当是比原 \(a_i\) 更优的边。于是不难得出如下建图方式:对于每一个 \(i\),从 \(i\)\(b_i\) 中所有排名小于等于 \(a_i\) 的点连边。这样一个图合法当且仅当所有环上的连边只有 \(i\to a_i\) 的连边,原因是显然的。

先连边 \(i\to a_i\),这些边是我们确定的。实际上现在我们要求的就是满足条件的新图的个数,不过求出图的个数之后我们还要算出每个图对应几种排列。事实上不难发现,我们对于每个 \(i\) 新连出去的边在 \(a_i\) 前可以乱排,后面也可以乱排。所以设 \(d_i\) 表示 \(i\) 新连出去的边的数量,则一张图的贡献为:

\[\prod d_i!(n-d_i-1)! \]

然后考虑怎样计算这个权值和。由于 \(a_i\) 是一个排列,所以图一定构成若干个环。对环缩点后剩下的边应该构成一个 DAG。然后考虑 DAG 计数的一个经典套路,考虑状压 dp,设 \(dp(S)\) 表示当前选出的环子集的导出子图的权值总和,枚举入度为 \(0\) 的子集然后容斥转移,有:

\[dp(S)=\sum (-1)^{|S|-|T|-1} dp(T)\times f(T,S-T) \]

其中 \(f(A,B)\) 表示将 \(B\)\(A\) 连边得到的权值和。注意到 \(B\) 中每一个点(注意这里和下文的 \(|A|,|B|\) 指的是总点数而非缩点后点数)向 \(A\) 中连边都是独立的,所以只需要考虑一个点向 \(A\) 的连边权值和即可。令 \(s=|A|\),然后考虑枚举连了多少条边,可以得到权值和为:

\[\sum_{i=0}^s \binom{s}{i}i!(n-i-1)! \]

做一些简单的代数变换可以知道上面式子的值就是 \(\tfrac{n!}{n-s}\),不过实际上没有这个必要,预处理或者直接在枚举的时候暴力计算就行。这样的话我们就得到了一个 \(O(3^c)\) 的做法,其中 \(c\) 为原图环的数量。显然这无法通过。

考虑到我们实际计算的时候不需要知道每一个环选没选,只需要知道每一个长度的环有多少个即可,这样只需要在转移的时候再乘一个组合数。我们对这个状态进行压缩,采用进制压缩的方法,最后状态数实际上是满足 \(\sum c_i\times i=n\)\(\prod (c_i+1)\) 最大值。当 \(n=40\) 时,这个值只有 \(1440\) 种。

最后的复杂度是 \(O(\text{state}(n)^2\times c)\),其中 \(\text{state}(n)\) 表示 \(n\) 的状态数。显然这是可以通过的。

F CF582D Number of Binominal Coefficients

\(\text{Link}\)

题目中有组合数 \(\binom{n}{m}\) 以及质数的幂, 不难联想到库默尔定理:

  • 对于一个组合数 \(\binom{n+m}{m}\),其含有质因子 \(p\) 的个数为 \(n+m\)\(p\) 进制下计算时的进位次数。

而这道题要求 \(p^\alpha\mid \binom{n}{k}\),也就是说 \(p^\alpha\mid \binom{(n-k)+k}{k}\)。而 \(n-k,k\) 都是小于等于 \(A\) 的,于是我们就是要求所有满足 \(a,b,a+b\le A\)\(a+b\)\(p\) 进制下计算进位次数 \(\ge \alpha\)\((a,b)\) 数量。

这个问题显然可以使用数位 dp 求解,设 \(f(i,j,0/1,0/1)\) 表示当前从高到低枚举到第 \(i\) 位,当前进位 \(j\) 次,当前有没有顶满前面的数字,以及钦定下一位是否有进位。转移比较繁琐,需要分类讨论多种情况,不过好在每种情况都不困难,注意系数不要算错就行。

最后的答案是 \(\sum f(n,i,0,0)+f(n,i,1,0)\)。复杂度是 \(O(\log^2 A)\) 的。

G AGC034E Complete Compress

\(\text{Link}\)

首先考虑枚举最后所有点抵达的点 \(x\),然后当前答案一定是 \(\tfrac 12 \sum dep_i\),我们只需要判断合法不合法即可。我们从根节点 \(x\) 开始考虑,看每一个子树内部的棋子到自己的距离和,然后发现这个问题可以转化为给定若干个数字,每次可以选出两个数字同时减一,问能否减成全 \(0\)

这个问题就很经典了,有一个结论是看这些数字的和 \(sum\) 与最大值 \(mx\),如果 \(mx\le sum-mx\) 则可以全部减完(偶数不剩,奇数剩一个);否则的话只能减去 \(sum-mx\) ,最大值还有一些没有减掉。

放到原问题中来看这个问题是可以解决的,因为这个最大值并不是不能用自己减,我们只需要递归到这个子树内,然后按照同样的流程看这个最大值的子树内最多能减掉多少,然后我们就可以算出当前节点最多能减掉多少了。如此算出根节点能减去的次数 \(cnt\),如果 \(cnt=\tfrac 12 \sum dep\) 则合法,记录答案最小值然后输出即可。复杂度是 \(O(n^2)\) 的。

H AGC020E Encoding Subsets

\(\text{Link}\)

首先考虑对一个字符串怎样求解,显然这是一个区间 dp。先枚举断点,为了去掉重复,我们需要钦定分出的第二段是一个字符或一个大括号。令 \(f(l,r)\) 表示压缩 \([l,r]\) 的方案数,\(g(l,r)\) 表示压缩 \([l,r]\) 为一个字符或一个括号的方案数。转移显然如下:

  • \(f(l,r)=\sum\limits_{k=l}^r f(l,k-1)\times g(k,r)\)
  • \(g(l,r)=\sum\limits_{d\mid r-l+1} f(l,l+d-1)\),其中 \(d\) 满足 \([l,l+d-1]\)\([l,r]\) 的一个循环节。

然后考虑原题,一个朴素的想法是将状态直接改为对子集压缩的方案数,这样 \(f\) 的转移不会变,只需看 \(g\) 的转移即可。枚举 \(d\) 之后 \([l,r]\) 被分成若干段,而一个合法的子集要求每一段都要相等,且这个相等的段是每一个原段的子集。于是可以得到这个相等的段必须是原段的交的子集。那么我们只需要求出压缩原段交的子集的方案数即可。

这里我们需要再修改一下状态的定义,将压缩原串 \([l,r]\) 改为压缩字符串 \(S\)。这样如果求出原段交的子集为 \(T\),那么 \(g(S)\) 就可以直接加上 \(f(T)\)。这个时候就没有办法直接枚举转移了,记忆化搜索即可。

这个做法看上去很暴力,但它实际上是可以通过的。事实上,在 \(n=100\) 时运算次数约 \(2.5\times 10^8\),可以通过。

I AGC036D Negative Cycle

\(\text{Link}\)

首先我们把整张图当成一个差分约束模型,这样没有负环就代表不等式组有解。

由于原图中 \(i\to i+1\) 的边不能删去,所以我们可以得到 \(x_i\ge x_{i+1}\)。移项后 \(x_i-x_{i+1}\ge 0\),令 \(c_i=x_i-x_{i+1}\),则有 \(c_i\ge 0\)

然后考虑新加的边,对于一条 \(i\to j(i<j)\) 的边,其对应限制条件为 \(x_i-1\ge x_{j}\),也就是 \(x_i-x_{j}\ge 1\)。改写一下可以知道 \(c_i+c_{i+1}+\cdots+c_{j-1}\ge 1\)。同理如果有一条 \(j\to i(i<j)\) 的边,那么条件就是 \(c_{i}+c_{i+1}+\cdots+c_{j-1}\le 1\)

然后将这个过程反过来,假如我们知道了 \(c_i\) 的取值,那么为了满足这个结果,有一些限制条件就要被删掉。根据上面的分析不难发现,如果有一段区间和等于 \(0\) 说明要删一条 \(-1\) 边,如果有一段区间和 \(\ge 2\) 说明要删一条 \(1\) 边。进一步分析发现,如果 \(c_i\ge 2\),那么把它改成 \(1\) 一定更优,因为这样不会增加区间和为 \(0\) 的区间且会至少减少一个区间和 \(\ge 2\) 的边。于是 \(c_i\in \{0,1\}\)

那么这样的话我们就可以直接 dp 了,令 \(dp(i,j)\) 表示当前令 \(c_i=1\),上一个 \(c\)\(1\) 的位置是 \(c_j\),删去的边的权值和的最小值。枚举上一个状态 \(dp(j,k)\),转移的时候用二维前缀和计算一下删去的边的权值总和即可。复杂度是 \(O(n^3)\) 的。

J AGC028D Chords

\(\text{Link}\)

发现圆上两条弦 \((a_1,b_1),(a_2,b_2)\) 相交当且仅当在数轴上 \([a_1,b_1],[a_2,b_2]\) 相交但不包含,于是断环为链,在序列上求解这个问题。进一步发现把连通块放到序列上之后,每一个连通块应该占据一个区间,且连通块之间只有包含和相离关系。

考虑拆贡献,对每一个连通块考虑其对答案的贡献。根据上面的分析,考虑连通块就是考虑区间,所以令 \(dp(l,r)\) 表示在区间 \([l,r]\) 内连出一个连通块,使得该连通块占据的区间恰好是 \([l,r]\) 的方案数。如果 \([l,r]\) 里面有向外连的边则这个连通块显然不可能只占据 \([l,r]\),跳过这种情况。

接下来既然要求这个连通块恰好占据 \([l,r]\),说明 \(l,r\) 必然联通。求连通图方案数有一个经典套路就是容斥,用总方案数减去不联通方案数。总方案数是好求的,把没有匹配点的点乱连即可;容斥的话枚举 \(i\) 所在连通块的最后一个点 \(k\),这一部分方案数为 \(dp(i,k)\),然后乘上后面的点乱连的方案数即可。

最后求出 \(dp(i,j)\) 后,再乘上外面的点乱连的方案数就可以得到这个区间的所有连通块对答案的贡献了。复杂度是 \(O(n^3)\) 的。

K AGC022F Checkers

\(\text{Link}\)

首先我们发现每一个点被作为对称中心只有一次,也就是说对于每个 \(B\),只有一个 \(A\) 会关于它对称。也就是说如果连边 \(B\to A\),这个过程会形成一棵树。容易发现,最后我们的答案一定可以写成 \(\sum c_i2^{d_i} x^i\),而由于 \(2^n\) 远小于 \(x\),所以我们可以认为只要一个点的 \((c_i,d_i)\) 不同,答案就不同。

\(d_i\) 是好计算的,实际上就是这个点在树上的深度。而 \(c_i\) 就不是很好求了,首先我们在 \(i\) 的父亲处会操作它的儿子,所以有一些儿子的 \(c\) 和父亲的 \(c\) 相等,有一些则不等。实际上若一个点的儿子数量为 \(son_i\),则它有 \(\lfloor\tfrac{son_i}2\rfloor\) 个儿子和自己的 \(c\) 相等。然后对于每一个儿子,它还要和它的儿子进行操作,每操作一次就会取一次反,那么每一个 \(c_i\) 还要在它父亲的基础上再乘一个 \((-1)^{son_i}\)

这个时候我们考虑 dp,从上往下构造这棵树。设 \(dp(i,j)\) 表示当前放了 \(i\) 个点,最后一层有 \(j\) 个节点的儿子数为奇数。枚举下一层的节点个数 \(k\),则这之中会有 \(t=\tfrac{k-j}2\) 个节点的初始 \(c_i\) 与它父亲相同。接下来再枚举下一层中最终的 \(c_i\) 与父亲相同的点数 \(p\),显然为了让点数达到 \(p\),我们需要将 \(|t-p|\) 个节点的儿子数量设为奇数以更改它的 \(c\)。于是转移方程为:

\[dp(i+k,|t-p|)=\sum dp(i,j)\binom{n-i}{k}\binom{k}{p} \]

于是我们就可以在 \(O(n^4)\) 的复杂度内解决这个问题。

L UOJ607【UR #20】跳蚤电话

\(\text{Link}\)

显然考虑树形 dp 求解这个问题。设 \(f(x)\) 表示初始集合 \(S=\{fa_x\}\) 时,将 \(x\) 子树内所有边连上的方案数(注意这里显然也包含 \((x,fa_x)\) 这条边)。那么此时答案非常好统计,简单计算可以得到:

\[ans_u=\frac{(siz_u-1)!}{\prod\limits_{v\in son_u} siz_v!}\prod_{v\in son_u}f(v) \]

但是现在的难点在于从 \(f(v)\) 转移到 \(f(u)\)。由于 \(f(u)\) 的初始集合实际上是 \(\{fa_u\}\), 所以我们的操作有两种:

  • 先连边 \((u,fa_u)\),然后接下来按照 \(ans_u\) 的方案连边即可。
  • 先把 \(ans_u\) 操作过程中的 \(u\) 当成 \(fa_u\),在第二次需要用到 \(u\) 进行连边之前把 \((u,fa_u)\) 连上,剩下的部分和 \(ans_u\) 一致。

第一种操作的系数很好算,就是 \(1\)。第二种略显麻烦,考虑枚举 \(ans_u\) 操作过程中第一次连边连向的子树 \(v\),单独拿出这个子树的操作序列 \(f(v)\);然后剩下的子树会构成一个操作序列,根据上面所说的结论,在执行第二个操作序列中的操作之前必须要进行连 \((u,fa_u)\) 的操作,所以我们把这个操作接到第二个操作序列前面。

那么最后将两个操作序列合并的方案数就是答案,不过还需要注意此时我们要固定操作序列的第一个位置是连向 \(v\) 子树的,不然的话就会和第一种操作重复。

计算后发现答案为:

\[\prod_{v\in son_u} f_v \times \sum_{v\in son_u}\dfrac{(siz_u-siz_v-1)!}{\prod\limits_{v'\in son_u\land v'\ne v} siz_{v'}!}\times \frac{(siz_u-1)!}{(siz_v-1)!(siz_u-siz_v)!} \]

化简后得:

\[\frac{(siz_u-1)!}{\prod\limits_{v\in son_u} siz_v!}\prod_{v\in son_u}f(v)\times \sum_{v\in son_u} \frac{siz_v}{siz_u-siz_v} \]

综合一下不难看出,\(f(u)\) 实际上可以用 \(ans_u\) 来表示,有:

\[f(u)=ans_u\times (1+\sum_{v\in son_u} \frac{siz_v}{siz_u-siz_v}) \]

这就是最后的转移。做一次树形 dp 即可,复杂度 \(O(n)\)

M UOJ181【UR #12】密码锁

\(\text{Link}\)

做这道题之前需要了解一个竞赛图上 SCC 计数的套路:由于竞赛图缩点后会形成一条链,所以每个强联通分量会对应一个前缀,而这个前缀满足这个前缀中所有点都指向外面的点。我们称这样的一个前缀为一个割集,而统计 SCC 数量实际上就是统计割集数量。

那么这道题让我们统计 SCC 期望个数,只需要统计每个割集的出现概率求和即可。现在来考虑怎样求出割集。观察数据范围发现 \(m\) 不是很大,在可以状压的范围内,考虑从这里入手。现在我们希望将一个割集的出现概率变得只和与它相连的特殊边有关;假如这个割集没有特殊边,设其大小为 \(x\),概率自然为 \(0.5^{x(n-x)}\),而此时每一条特殊边相当于给这个概率乘上了 \(2P\)。于是我们只需要统计 \(2P\) 这个信息即可。

由于现在的概率只和特殊边有关,我们可以将特殊边构成的连通块分开考虑。对于一个连通块,直接暴力枚举把它的哪些点加入割集,算出点集大小以及对应概率。把所有连通块做完之后进行一个背包 dp,就可以求出每种大小的割集的出现概率,然后乘上 \(0.5^{x(n-x)}\) 后就是最终答案。

由于 \(m\) 条边形成的连通块的点数是 \(O(m)\) 的,所以复杂度是 \(O(2^{m}n+n^2)\) 的,可以通过。

N UOJ370【UR #17】滑稽树上滑稽果

\(\text{Link}\)

首先题目中要构造树就是个幌子,显然每做一次 \(\text{and}\) 都会让数值变小,所以造一条链一定是更优的。同时再观察一下可以发现,最后我们得出的一定是所有数的 \(\text{and}\) 值;那么我们实际上在不超过 \(\log V\) 次操作之后就没有办法改变数字的值了。

于是可以想到一个朴素的 dp:设 \(dp(i,j)\) 表示当前放了 \(i\) 个数,当前 \(\text{and}\) 值为 \(j\) 的最小价值。转移是容易的,最后答案是 \(\min dp(i,j)+(n-i)\times S\),其中 \(S\) 是所有元素的 \(\text{and}\) 和。这样做的复杂度是 \(O(nV\log V)\) 的。

考虑优化。我们发现一个关键点是 \(j\) 总是向他的子集转移,所以我们从大往小枚举状态实际上就可以起到转移的效果。问题在于我们最后统计答案需要用到 \(i\) 这一维,这也是容易处理的,采用费用提前计算的思想,初始时设 \(dp\) 值为 \(n\times S\),每次转移时先减去 \(S\) 再加上对应值即可完成转移。

同时,在转移过程中,我们也不需要枚举每一个数字,采用枚举子集并判断的方法转移即可;判断的时候需要判断某个数的子集有没有出现过,提前做一次高维前缀和即可。综上,我们可以在 \(O(3^{\log V})\) 的复杂度内解决这个问题。

O UOJ312【UNR #2】梦中的题面

\(\text{Link}\)

首先题目中有一个 \(b^i-c\) 的形式,先考虑 \(c=1\),那么它可以写成 \(b^i-1\) 的形式。实际上这个形式比较有意思,因为如果将所有运算放在 \(b\) 进制下来看,这个限制相当于说每一个 \(x_i\) 可以在 \(1\sim i\) 位上放 \(0\sim b-1\) 的任何数字。最后我们要求若干个 \(x_i\) 和小于 \(n\),又由于 \(n<b^{m+1}\),所以 \(n\) 最多也只有 \(m+1\) 位。

那么我们就可以考虑数位 dp 了,设 \(dp(i,j,0/1)\) 表示当前考虑到从高往低第 \(i\) 位,钦定下一位进位为 \(j\),当前位是否顶满的方案数。枚举 \(i,j\) 以及给上一位的进位 \(k\) 进行转移,由于第 \(i\) 位上有 \(i\) 个数字可以填,所以这里我们需要计算一下 \(i\) 个数字和在某个范围内的方案数。这个可以 \(O(m^2b)\) 预处理求出来。那么这一部分转移的复杂度就是 \(O(m^3)\) 的了。

考虑 \(c=0\),实际上就是说有一些数可以在第 \(i+1\) 位填一个 \(1\) 而后面的全部为 \(0\)。这里我们需要给 dp 状态加一维,表示我们当前已经放了多少个形如这样的数字,那么当我们遍历到后面的一个位置的时候,这些数字已经钦定为 \(0\),所以不能再放置了,计算可以放置的数字个数的时候需要减掉。那么我们的复杂度就会上升至 \(O(m^4)\),不过这也是足够通过的了。

posted @ 2025-03-22 18:31  UKE_Automation  阅读(113)  评论(0)    收藏  举报