【UER #13】双料高级特工(alt version)

听说有人说官方题解不写 alt version? 当然这个 version 前半部分是没有原版好的,这题还可以 Bostan-Mori,原版才彻底把容斥卡爆了。所以推荐大家去做原版。

为什么原版被容斥卡掉了呢,因为在前半部分要做很多次 \(m^2\) 的多项式卷积。但恰好有一个不用容斥的做法在前半部分复杂度可以 \(/n^2\),于是 \(m\) 就能开到 \(1000\) 了,是不是很神奇。



把整个题分为两步,先 DP 出 \(c\) 升序排序后的情况,再还原出原来的情况。

不妨设将 \(c\) 升序排序后的序列叫 \(b\),考虑先 DP 出 \(b\) 相邻位置的关系:

对于这种物品很小的背包问题,可以从高到低做数位 DP,依次确定 \(b_i\) 的二进制数位。

假设我们确定了最高的若干位,此时相邻的 \(b_i\) 关系为 \(S\)(信息量 \(2^{n-1}\))。

决定更低一位的时候,从左到右逐点确定。设 \(dp_{i,S,0/1,x}\) 表示确定了前 \(i\) 个数字的当前位,相邻的 \(b_i\) 关系为 \(S\),上一个数字的当前位为 \(0/1\),比当前位低的所有位向当前位进位了 \(x\)。

前面部分的复杂度为 \(2^n n^2\log m\)。

令 \(F_S = \sum\limits_{x=1}^{m} f_{1, S, x, x}\),我们就知道了所有 \(b\) 的相邻位置关系下,有多少种可能的原密码,接下来尝试复原出原问题的答案:

我们逐点变换出答案,用 \(g_{i, S, T, k}\) 表示:

考虑了 \(c\) 的前 \(i\) 位,\(c\) 的前 \(i\) 个元素相邻位置间的关系是 \(S\)( \(S\) 是一个长度为 \(i-1\),由 <, =,> 构成的字符串)。

\(c\) 的后 \(n-i+1\) 个元素在排序后,相邻位置间的关系是 \(T\)( \(T\) 是一个长度为 \(n-i\),只由 <, = 构成的字符串)。

\(c\) 的后 \(n-i\) 个元素中,有 \(k\) 个比 \(c\) 的第 \(i\) 个元素小(即 \(c_i\) 在后缀中的排名)。

初始化 \(\forall k \in [n], g_{1, \varepsilon, T, k} = F_T\) 即可。

可以观察到 \(g\) 的状态数为 \(\sum\limits_{i=1}^n 3^{i-1}2^{n-i+1}(n-i+1)\),因此总状态数是 \(O(3^n)\) 的。转移直接暴力,或者用前缀和优化转移能快一点,但对复杂度没有影响。

对于第二部分,一个减小常数的方法是一边 dfs 前面的状态一边计算 DP,这样内存访问更友好。

综上我们在复杂度 \(O(2^n n^2 \log m + 3^n)\) 内解决了这个问题。

posted @ 2026-06-12 22:40  Rainbow_qwq  阅读(141)  评论(0)    收藏  举报