zoukankan      html  css  js  c++  java
  • ARC-124 部分题解

    E

    直接统计原式不好做,注意到首先我们应该知道怎样的 (x) 序列是合法的,那么不妨首先来统计一下合法的 (x) 序列数量。

    (b_i)(i) 向右给的球数,那么有((i = 1) 特殊考虑):

    [x_i = a_i + b_{i - 1} - b_i = a_i - (b_i - b_{i - 1})(i > 1) ]

    那么考虑令 (b) 的差分数组 (d, d_i = b_i - b_{i - 1}(i > 1), d_1 = d_1 - d_n),根据上式 (x)(d) 构成双射。

    但注意到 (d) 不与 (b) 构成双射,(d) 不方便限制大小但 (b) 好统计,那么不妨观察一下哪些 (b) 会对应同一个 (d)

    不难发现若将 (b) 整体 (+x) 会对应一个相同的 (d),反之也成立。

    于是我们考虑钦定 (min b_i = 0) 的序列合法,那么此时合法的 (b) 序列就可以与 (x) 构成双射且容易得到 (x) 序列。

    那么考虑一下合法的 (x) 序列的数量,等价于要求:

    [egin{cases} min b_i = 0 \ b_i le a_i (1 le i le n) end{cases}]

    容易使用容斥解决,答案为:

    [prod (a_i + 1) - prod a_i ]

    那么现在回到原题,注意到所求答案式子比较奇怪,那么基本上就要考虑组合意义了。

    容易发现 (prod x_i) 的组合意义:有 (n) 个盒子,第 (i) 个盒子有 (x_i) 个球,问从每个盒子拿出 (1) 个球的方案,球有标号。

    考虑 ( m dp),因为值域很大,所以不能将值域记录在状态内。

    但注意到每个盒子剩下的球必定是自己拿出去剩下的和之前的盒子给过来的,确定每个盒子取自己的球还是取之前盒子的球后方案数就是独立的。

    因此可以令 (f_{i, 0 / 1, 0 / 1}) 表示当前考虑完前 (i) 个盒子,当前盒子取出的球是自己剩下的还是之前盒子传过来的,当前是否选过一个 (b_j = 0)

    转移考虑下一个位置选球状态和当前传过去多少个球,容易优化到 (mathcal{O}(1)),复杂度 (mathcal{O}(n))

    需要注意的是:因为人构成环,所以第一个人的选球状态需要一开始钦定,因此需要做两边上述 ( m dp)

    F

    首先我们将 (n, m) 都减小一,将矩阵平移到以左下角为原点。

    首先考虑一个暴力,由于两个人只会恰好相遇一次,因此考虑枚举两个人的相遇点 ((p, q))

    那么就只要算出 (f_{p, q}, g_{p, q}) 分别为两个人从起点 / 终点同时走到 ((p, q)) 的方案,两者显然等价,于是我们一下仅考虑算 (f)

    令第一个人在纵、横方向上分别走了 (x_1, y_1) 步,第二个人类似地走 (x_2, y_2) 步。

    那么两个人在 ((p, q)) 相遇当且仅当:

    [egin{cases} p + x_1 = n \ x_2 = p\ y_1 = y_2 = q end{cases} ]

    接着我们有如下观察:

    • 两个人相遇位置一定是同一行连续的一段区间。

    于是我们可以考虑枚举这一行第一个相遇的位置 ((p, i)),之后为了强制钦定两者在 ((p, q)) 再次相遇一次,那么他们两者在横方向上一定要恰好走了 (q - i) 步。

    容易发现两者在横方向上都走 (q - i) 步的方案为:(inom{2(q - i)}{q - i}),那么就有转移:

    [f_{p, q} = dbinom{n + 2q}{n} imes dbinom{n}{p} imes dbinom{2q}{q} - sumlimits_{i < q} dbinom{2(q - i)}{q - i} f_{p, i} ]

    复杂度 (mathcal{O}(n ^ 3)),考虑优化。

    容易发现后面的和式部分转移系数与 (p) 无关,那么不妨考虑将所有 (f) 合起来一起转移:

    (g_q = sumlimits_p f_{p, q}),那么应该有转移:

    [g_q = dbinom{n + 2q}{n} dbinom{2q}{q}2 ^ q - sumlimits_{i < q} dbinom{2(q - i)}{q - i} imes g_i ]

    但此时存在一个问题,这样无法计算得到每个点确切的值因而无法与终点到该点的方案进行合并。

    问题在于上面的做法是在我们确定相遇点基础上进行的,那么我们是不是可以先不确定相遇点呢?

    根据上述判定相交的方法可以发现,无论两者怎么走,若一起在纵方向上走 (n) 步之后在同一列就一定会相遇。

    因此本质上横纵方向上的移动是独立的,纵方向上在哪个位置相遇与横方向上哪个位置相遇是无关的。

    换句话说,对于纵方向上相遇的每种方案都可以与横方向上相组合。

    容易发现纵方向上相遇的每种方案就是任意一种纵方向方案在第 (n) 个操作位置后划开,前半部分放在起点到 ((p, q)) 的路径上,后半部分放在 ((p, q)) 到终点的路径上。

    因此我们在计算所有方案的时候可以考虑先在计算横方向操作的时候将纵方向操作位置预留,最后再将任意一种方案插入进去就可以了。

    那么最终的答案就是:(sumlimits_i ^ m inom{2n}{n} imes g_i imes g_{m - i}),下面考虑如何求 (g)

    根据上述对 (g),重新的定义,我们不难发现转移:

    [g_i = dbinom{n + 2i}{n}dbinom{2i}{i} - sumlimits_{j < i} dbinom{2(i - j)}{i - j}g_j ]

    此时用半在线卷积转移 (g) 可以做到 (mathcal{O}(n log ^ 2 n)),还不够优秀,考虑继续优化。

    我们此时发现:对于在同一行仅有横方向在走的情况下保证两个人不相遇是很容易的。

    将第一个人看作左括号,第二个人看作右括号(也可以换过来),这个问题等价于问有多少个完美匹配括号序列使得其不能划分成两个完美匹配括号序列。

    根据之前的经验,容易得知这就是前一项的卡特兰数。

    考虑强制首尾括号匹配,那么只需要先在首尾填好括号让中间放入一个长为 (n - 1) 的完美匹配括号就可以与上述括号序列构成双射。

    因此我们可以考虑枚举最后一个相遇的位置,那么前面的方案就可以使用钦定的方法算了:

    (h_i = inom{n + 2i}{n}inom{2i}{i}),那么就有转移:

    [g_i = h_i - 2sumlimits_{j < i} c_{i - j - 1} imes h_j ]

    这就是一个卷积,直接使用 ( m NTT) 优化即可,复杂度 (mathcal{O}(n log n))

    GO!
  • 相关阅读:
    前端
    前端
    数据库
    代码块
    装饰器
    函数 初识函数
    相识python --------文件操作
    相识python --------str字符串 int整形 bool布尔值 tu元祖 set()集合 dict 字典的数据补充
    【openstack报错】【因更新包而致】IncompatibleObjectVersion: Version 1.9 of Instance is not supported
    开博第一篇
  • 原文地址:https://www.cnblogs.com/Go7338395/p/15306151.html
Copyright © 2011-2022 走看看