zoukankan      html  css  js  c++  java
  • ARC104 (D~F) 简要题解

    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 的方案数,有

    [large{ f[l][r][h] = sum_{i=l+1}sum_{y=1}^xf[i][r][x-1] imes f[l][i-1][y]\ +sum_{i=l+1}sum_{y=1}^{x-2}f[i][r][y] imes f[l][i-1][x] imes [h_i ge x-1] } ]

    前缀和优化即可。

    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;
    }
    
  • 相关阅读:
    企业使用数据库的12种姿势
    回归架构本质,重新理解微服务
    Java中随机数的产生方式与原理
    自动类型转换、强制类型转换、作用域、整型表数范围
    创建自定义类的对象数组
    CentOS上安装比较习惯的代码编辑器
    ubuntu 15.04 的安装遇到的问题及其解决方法
    算法思想篇(1)————枚举算法
    初来乍到
    Eclipse中获取html jsp 标签的属性提示信息方法
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13781779.html
Copyright © 2011-2022 走看看