ARC104 (D~F) 简要题解
这场出题人应该很擅长计数,尤其是不重不漏的按方案计数。
Multiset Mean
元素范围为 (1 o n),每个元素最多出现 k 次,对于所有可能的集合,求出其平均数,问对于任意 (i in [1,n]) 作为平均数的方案数事多少。
(1 le n,k le 100)
肯定是个 dp 题,设 (f[x][y]) 表示用前 x 个数,拼出来总和为 y 的方案数,转移 (f[x][y] = sum f[x-1][y-kx]),用前缀和优化一下即可做到 (Theta(n^4)),但这咋求平均数。
发现对于 x 事平均数的方案,对于小于 x 的事 ((x-1),(x-2),(x-3)cdots),大于的事 ((x+1),(x+2)cdots)
让集合中的每个元素都减 x,则最终集合的和是 0 则 x 就是平均数,所以考虑正负贡献分别考虑,小于 x 的贡献是 (-1 o -(x-1)) 的,大于 x 的贡献是 (1 o n-x) 的,所以就是小于的凑出一个数 -t,大于的凑出一个数 t,这样就行了。
另外发现第二维可以缩小范围达到 (125000) 左右来优化常数。
Random LIS
神仙题。
考虑我们的最终序列,将它按 (a_i) 排序使它的最长上升子序列等于排序后 id 的最长上升子序列。
那么优先比较 (a_i),然后 id 大的放前面,这样转化后的排列最长上升子序列长度就是固定的了。
枚举全排列,让 (a_i) 不降,其中的限制是 (a_i (le,<) a_{i+1}),如果 (id_i > id_{i+1}),那么有等号,否则没有。
我们考虑把所有的小于号变成小于等于,显然直接把后面的减一即可。
所以现在就是从点 (1, 1) 开始到 ((n+1,infty)) 的方案数,这个可以容斥求的。
最终复杂度 (Theta(n! imes n^3))
Visibility Sequence
容易发现每个位置的取值并不重要,重要的事它们的相对顺序,所以高度就变成 (Theta(n)) 级别的了。
考虑每个位置事哪些位置的控制点,我们令 0 处有一个 (infty) 高度的楼,令每个位置向前一个 (H_j > H_i) 的位置 j 连边,这样你就发现每个位置的子树是一个原序列上的区间。
我们考虑让序列 P 和 H 建立起一一映射的关系。因为有 (X_i) 的限制,所以我们让 (H_i) 尽可能小。
容易发现,对于一种已确定的 P,那么就可以建出树来,左兄弟的 H 一定小于等于自己,父亲的 H 一定大于自己,孩子们的 H 一定小于自己。因此不难确定 (H_i=max{H_s+1,H_b}),每个 P 都对应着一个 H,也很好构造每个合法的 H 对应着一个 P。
因此我们有了区间 dp 的想法,设 (f[l][r][h]) 表示在区间 ([l,r]) 中,l 作为根,高度为 h 的方案数,有
前缀和优化即可。
const int P = 1e9 + 7;
const int N = 105;
ll f[N][N][N], s[N][N][N], X[N], n;
int main() {
read(n); X[1] = ++n;
for (int i = 2;i <= n; i++) read(X[i]);
for (int i = n;i >= 1; i--) {
f[i][i][1] = 1;
for (int j = 1;j <= min(X[i], n); j++) s[i][i][j] = 1;
for (int j = i + 1;j <= n; j++) {
for (int x = 2;x <= min(X[i], n); x++) {
ll res = 0;
for (int t = i + 1;t <= j; t++) if (X[t] >= x - 1)
res = (res + s[i][t-1][x] * f[t][j][x-1] + s[t][j][x-2] * f[i][t-1][x]) % P;
s[i][j][x] = ((f[i][j][x] = res) + s[i][j][x-1]) % P;
}
}
}
write(s[1][n][n]);
return 0;
}