1 条题解
-
0
D. 排列黑洞 题解
题意回顾
给定不完整的染色序列 (某些 待定),求能生成该序列的排列 的数量。染色过程见题目描述。
过程转化与区间 DP
将整个过程倒过来考虑:全黑时最终状态,每个格子 的分数 等于它在被染黑后作为“最近黑格”被其他格子选中的次数。正向看,第 次染色不加分;之后的 次每次给当时最近的黑格加 。
假设我们固定某个区间 ,且已知在染色该区间内任何一个格子之前, 和 已经是黑色的(若存在)。那么区间内第一个被染色的点 必然选择 和 中较近的一个进行加分(距离相等时选编号小的,即 )。此后 变黑,将区间划分为 和 ,这两部分又面临类似的问题,只是外侧的黑格发生了变化:左子区间的右外侧是 ,右子区间的左外侧也是 。
这启发我们使用区间 DP。
定义状态: 表示考虑区间 被染色的所有合法排列方案数,满足:- 在该区间染色过程中, 额外增加了 ;
- 额外增加了 。
这里“额外增加”指的是区间内部的点染色时选择 或 作为最近黑格的总次数。
区间内部点的分数在递归到更小的子区间时会体现为其外侧格子的 或 贡献。最终答案:整个序列 没有外侧黑格,故要求 。若 ,则 只能为 ; 时 只能为 。
答案即为 。
转移方程
对于区间 ,枚举该区间内第一个被染色的点 ()。
选择给 还是 加分,取决于距离比较:- 若 (即 ),则 给 加 分,体现为 时从 转移;
- 否则 给 加 分,体现为 时从 转移。
设左子区间 ,右子区间 。
在 中, 作为右外侧黑格,会获得来自 的贡献 (即 中的 );
在 中, 作为左外侧黑格,会获得来自 的贡献 (即 中的 )。
因此 最终的分数 。若题目中 已经固定,则必须满足 ;否则任意非负整数均可。此外, 选为第一个后,左右区间的染色顺序可以任意交错,只需保持各自内部顺序。区间总共有 个点(除 外),左区间有 个,右区间有 个。排列顺序的方案数要乘上组合数 以选定左区间点出现的时机。
综上,转移方程为(省略边界细节):
若 :
$$\begin{aligned} &dp[l][r][x][y] = \\ &\sum_{\substack{i\le \lfloor(l+r)/2\rfloor \\ x\ge 1}} \binom{r-l}{i-l} \sum_{j,k} dp[l][i-1][x-1][j] \cdot dp[i+1][r][k][y] \\ &+ \sum_{\substack{i > \lfloor(l+r)/2\rfloor \\ y\ge 1}} \binom{r-l}{i-l} \sum_{j,k} dp[l][i-1][x][j] \cdot dp[i+1][r][k][y-1] \end{aligned} $$若 固定:
$$\begin{aligned} &dp[l][r][x][y] = \\ &\sum_{\substack{i\le \lfloor(l+r)/2\rfloor \\ x\ge 1}} \binom{r-l}{i-l} \sum_{\substack{j,k \\ j+k=v}} dp[l][i-1][x-1][j] \cdot dp[i+1][r][k][y] \\ &+ \sum_{\substack{i > \lfloor(l+r)/2\rfloor \\ y\ge 1}} \binom{r-l}{i-l} \sum_{\substack{j,k \\ j+k=v}} dp[l][i-1][x][j] \cdot dp[i+1][r][k][y-1] \end{aligned} $$边界条件:
- 当 时,空区间仅 ,其余为 。
- 当 时,左边没有 ,强制 ;当 时,强制 。
- 所有 以及中间枚举的 都有取值范围,且不能超过 ,实际上有更紧的上界。
关键性质:分数上界为
证明:固定位置 ,考虑左侧的那些会给 加分的格子 。
对于相邻两个这样的格子 ,在 被染色时, 必须是最近的黑色格子(因为 当时尚未染色,是白色)。
此时 与 的距离为 。若 已经被染色(它会在 之后才染色),则 也是黑色,且更近?但 染色时 还是白的,所以不构成干扰。然而,在 染色时, 也必须还是最近的黑色格子(否则 不会给 加分)。因此有:否则,若 ,则 会更靠近 而不是 ,导致 给 加分而非 。
由此可得每个这样的格子到 的距离至少翻倍,因此数量 。右侧同理。
所以 。
实际 ,,故 的上限可设为 。
复杂度分析
- 状态数:,约 。
- 转移:枚举 和 (范围 ),复杂度 ,约 ,实际常数小且很多状态不可达,可在 秒内通过。
实现细节
- 预处理组合数 模 。
- DP 数组用
int或long long,注意取模。 - 设置 作为 上限。
- 边界:当 时只处理 ; 时只处理 。
- 转移时注意 或 不能越界。
- 对于 固定的情况,需匹配 ,且 均 。
- 空区间 返回 时为 。
#include <bits/stdc++.h> using namespace std; const int MOD = 998244353; const int MAXN = 105; const int MAXLOG = 9; // log2(100) ≈ 7, 取9足够 int n; vector<int> s; int C[MAXN][MAXN]; int dp[MAXN][MAXN][MAXLOG][MAXLOG]; bool vis[MAXN][MAXN][MAXLOG][MAXLOG]; void add(int &a, int b) { a += b; if (a >= MOD) a -= MOD; } int mul(int a, int b) { return 1LL * a * b % MOD; } // 记忆化搜索 int solve(int l, int r, int x, int y) { if (l > r) { return (x == 0 && y == 0) ? 1 : 0; } // 边界:左右外侧不存在时,对应分数必须为0 if (l == 1 && x != 0) return 0; if (r == n && y != 0) return 0; if (x < 0 || y < 0) return 0; if (x >= MAXLOG || y >= MAXLOG) return 0; // 超出范围不可能 if (vis[l][r][x][y]) return dp[l][r][x][y]; vis[l][r][x][y] = true; int &res = dp[l][r][x][y] = 0; int len = r - l; // 除了i之外的节点数 for (int i = l; i <= r; ++i) { int leftLen = i - l; int rightLen = r - i; int ways = C[len][leftLen]; // 选择左边点出现的位置 if (i <= (l + r) / 2) { // 给左边加分,需要x >= 1 if (x < 1) continue; for (int j = 0; j < MAXLOG; ++j) { // 左区间对i的加分(dp[l][i-1]的y) for (int k = 0; k < MAXLOG; ++k) { // 右区间对i的加分(dp[i+1][r]的x) if (s[i] != -1 && j + k != s[i]) continue; int leftWays = solve(l, i - 1, x - 1, j); int rightWays = solve(i + 1, r, k, y); if (leftWays && rightWays) { add(res, mul(ways, mul(leftWays, rightWays))); } } } } else { // 给右边加分,需要y >= 1 if (y < 1) continue; for (int j = 0; j < MAXLOG; ++j) { for (int k = 0; k < MAXLOG; ++k) { if (s[i] != -1 && j + k != s[i]) continue; int leftWays = solve(l, i - 1, x, j); int rightWays = solve(i + 1, r, k, y - 1); if (leftWays && rightWays) { add(res, mul(ways, mul(leftWays, rightWays))); } } } } } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); // 组合数预处理 for (int i = 0; i < MAXN; ++i) { C[i][0] = C[i][i] = 1; for (int j = 1; j < i; ++j) { C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; } } int t; cin >> t; while (t--) { cin >> n; s.resize(n + 1); for (int i = 1; i <= n; ++i) cin >> s[i]; memset(vis, 0, sizeof(vis)); int ans = solve(1, n, 0, 0); cout << ans << "\n"; } return 0; }总结
本题将染色过程转化为递归的“区间选根”模型,利用区间 DP 计数,并通过分数的对数级上界压缩状态,在 内求解。
- 1
信息
- ID
- 7125
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 6
- 已通过
- 1
- 上传者