1 条题解
-
0
题解:支配点计数问题
题目理解
我们有一个点集 ,其中 和 都是 到 的排列。对于每个点 ,我们想知道有多少个排列 使得在执行给定的伪代码后,最后保留的点是 。
伪代码的逻辑是:遍历排列,如果当前点的两个坐标都大于等于已保存点的对应坐标,就更新保存的点。
问题转化
关键观察:一个点 能够成为最后保存的点,当且仅当在排列中:
- 点 出现在所有能"支配"它的点之前(即所有 且 的点 )
- 点 出现在所有它能支配的点之前(即所有 且 的点 )
实际上,条件可以简化为:点 必须是其"支配集合"中在排列里最早出现的点。
算法思路
1. 支配关系分析
对于点 ,定义:
- 被 支配的点:满足 且 的所有点
- 支配 的点:满足 且 的所有点
点 能成为最后保存点的充要条件是:在排列中, 出现在所有支配它的其他点之前。
2. 概率与计数
设 是支配点 的点集(包括 自身),大小为 。
在随机排列中,点 出现在 中第一个的概率是 。
因此,总排列中 成为最后保存点的方案数为:
3. 特殊情况处理
但是有一个特殊情况:如果存在点 严格支配 (即 且 ),那么 永远不可能成为最后保存点,因为 出现时会覆盖 。
因此:
- 如果存在严格支配 的点,则
- 否则,,其中 是支配 的点数
代码解析
constexpr int MOD = 1000000007; int fac = 1, n, a[100007], b[100007], pos[100007], f[100007]; // 快速幂求逆元 inline int qp(int a, int b, int t = 1) { for (; b; b >>= 1, a = a * a % MOD) if (b & 1) t = t * a % MOD; return t; } // 树状数组用于二维偏序计数 struct BIT { int data[100007]; void add(int x, int k = 1) { for (; x <= n; x += x & -x) { data[x] += k; if (data[x] >= MOD) data[x] -= MOD; } } int sum(int x, int k = 0) { for (; x; x -= x & -x) k += data[x]; return k % MOD; } int query(int l, int r) { return sum(r) - sum(l - 1); } } tree;主算法流程:
signed main() { cin >> n; // 计算 n! for (int i = 2; i <= n; i++) fac = fac * i % MOD; // 读入并建立映射 for (int i = 1, x, y; i <= n; i++) cin >> x >> y, a[x] = y, pos[y] = i; // 第一遍树状数组:从后往前,计算每个点的支配者数量 for (int i = n; i >= 1; i--) { b[i] = tree.query(a[i], n); // 支配点i的点数 tree.add(a[i]); b[i] = qp(b[i], MOD - 2); // 存储逆元 } // 第二遍树状数组:动态规划计算答案 std::fill_n(tree.data, n + 1, 0); tree.add(1, qp(n, MOD - 2)); // 初始化 for (int i = 1; i <= n; i++) { if (!b[i]) // 如果支配点数为0(实际上是被严格支配) f[pos[a[i]]] = tree.sum(a[i]) * fac % MOD; else tree.add(a[i] + 1, tree.sum(a[i]) * b[i] % MOD); } for (int i = 1; i <= n; i++) cout << f[i] << '\n'; return 0; }关键技巧
1. 二维偏序处理
利用树状数组在 时间内处理二维偏序关系。
2. 逆元计算
使用费马小定理和快速幂计算模逆元,避免除法。
3. 动态规划
通过巧妙的DP转移,在遍历过程中同时判断严格支配关系和计算方案数。
时间复杂度
- 预处理阶乘:
- 两遍树状数组操作:
- 总体复杂度:
算法标签
- 组合数学
- 二维偏序
- 树状数组
- 概率与期望
- 模逆元
总结
本题的核心在于理解支配关系和排列概率。通过二维偏序技术快速确定每个点的支配集合,然后利用组合数学计算符合条件的排列数。算法充分利用了 和 都是排列的性质,实现了 的高效解法。
- 1
信息
- ID
- 5387
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者