加载中...

CF div2 1035 D(逆向思维 + dp)

D

最近的一场CF div2的D题,个人认为这道题题意晦涩难懂,难度非常大,蒟蒻也是想了将近整整一天才弄明白了一点点qwq。。。

先回顾一下题意:\([1,n]\)\(n\) 个位置按顺序排列,每个位置有一个 \(token\)。共有 \(n\) 次取 \(token\) 的操作,其中第 \(i\) 次可以取第 \([a_{i},i]\)\(token\) 中的任意一个(\(a_{i}\in [0,i]\))。特殊地,当 \(a_{i}=0\) 时,此次操作不能取任何 \(token\);否则一定会取走对应区间内的某一个存在的 \(token\)。可见 \(n\) 次操作可构成的 \(n\) 个区间序列个数为 \((n + 1)!\)(显然,证明略)。每一种区间序列对应的不同的取 \(token\) 序列个数记作 \(f(a)\)(两个 取 \(token\) 序列 不同,当且仅当存在第 \(t\) 次操作,取走的 \(token\) 种类不同(或没取,也算作一个不同的种类)),求这 \((n + 1)!\) 种区间序列的 \(f(a)\) 之和模给定模数 \(m\) 的值。(之后才明白为什么没有给定模数:如果给定了模数,那么答案就至多有 \(5000\) 种,这样就存在通过打表暴算来 \(AC\) 本题的可能。)

求一个给定区间序列的 \(f(a)\) 本身就是一件十分困难的事情。而本题并不是让求给定 \((a_{1},a_{2},...,a_{n})\)\(f(a)\) 的值,而是让求所有可能的序列 \(a\)\(f(a)\) 之和。其实这样我们就可以逆向思考:本题答案可以等价于求:所有可能的 取 \(token\) 序列 的 \((a_{1},a_{2},...,a_{n})\) 数量之和。因为某个区间序列 \((a_{1},a_{2},...,a_{n})\) 与 某个取 \(token\) 序列可以建立起一一映射的关系,因此正难则反,考虑如何解决转化后的题意:

由于第 \(i\)\(token\) 只可能被第 \([i\backsim n]\) 个区间取得,因此可以考虑从后往前 \(dp\)

\(dp[i][j]\):考虑 \(token[i \backsim n]\),从第 \(i\)\(token\) 开始往后取,恰好有 \(j\)\(token\) 被取走,所有可能的 \(token\) 序列对应的 \((a_{1},a_{2},...,a_{n})\) 数量之和。(第二维的定义蒟蒻无法弄明白为什么要这样定义,怎样才能在下次遇到同类型题目时想到这样定义。。。希望有大佬能来指导我!!!)

决策第 \(i\)\(token\) 的情况:

  1. 不取第 \(i\)\(token\):此时完全等价于 \(a_{i}=0\),从第 \(i + 1\)\(token\) 开始取恰好 \(j\)\(token\),对应 \(dp[i + 1][j]\),直接转移过来即可:

\[dp[i][j] += dp[i + 1][j] \]

  1. 取第 \(i\)\(token\):也是本题最难理解的转移部分。显然 \(dp[i][j]\) 应当从 \(dp[i + 1][j - 1]\) 转移而来。此时应该这样考虑:在心中钦定好某一个 取 \(token[i+1,n]\) 序列,该序列会对应多个 \((a_{i+1},...,a_{n})\) 区间序列。现在要在开头添加一个 \(token[i]\),使得序列变为 \((a_{i},...,a_{n})\)。由于前面恰好取走了 \(j-1\)\(token\),故第\([i+1 \backsim n]\) 区间内已经用掉了 \(j - 1\) 个区间,因此此时还剩下 \((n-i+1)-(j-1)\) 个区间可以取走第 \(i\)\(token\)(给 \(token[i]\) 分配的区间数目,即 \(a_{i}\)\(i\) 的取值个数);且这些区间对应的 \(a_{k}\) 取值均为 \(1,2,...,i\)\(i\) 种取值(即每个 \(a_{i}\) 的取值个数均为 \(i\)),则每个 取 \(token\) 序列对应的区间序列数量会变为之前的 \((n-i+1-(j-1))*i\) 倍。因此转移为:

\[dp[i][j] += dp[i+1][j-1]*(n-i+1-(j-1))*i \]

两个转移合起来进行即可。最终根据状态定义,答案为:

\[\sum_{i=0}^{n} dp[1][i] \]

具体细节见代码。

code

posted @ 2025-07-08 17:35  jxs123  阅读(29)  评论(0)    收藏  举报