GMOJ 2020.10.29【NOIP提高A组】模拟
一套前三题较为简单但是并没有做出来的膜你赛
T1.6806achen
首先, (A), (B) 是可以对调的, 所以默认 (A < B)
可以发现, 如果 (A) 左边有大于2个点, 那么走完 (A) 左边方案唯一, 且最后停在 (A + 1), 对于(B) 同理.
所以方案数就为 (A + 1) 至 (B - 1) 的方案数.
设 (f[i]) 为从1到 (i) 的方案数, 显然 (f[i] = f[i - 3] + f[i - 1]).
还有一点特殊情况也十分好判.
T2.6808tree
首先假定根为(1), 答案可以分为两部分讨论 :
1.以(u)为根的子树中包含所有颜色, 那么 (u) 对答案的贡献为 (u)子树以外到 (u) 的最长链
2.以(u)为根的子树中没有完全包含任何颜色, 那么 (u) 对答案的贡献为 (u) 到 叶子节点的最长链
每个点的贡献是十分好算的, 问题在于如何判断这个点是否能贡献.
对于 1, 可以按 (dfs)序遍历所有点, 每个点到根的路径加1, 它与前一个颜色相同的点的 (lca) 到根的路径减1. 其实就是一次树上差分, 最后有1贡献的充要条件是点的和为 (m).
对于2, 只分别需要求出每种颜色的点的 (lca), 显然 (lca) 到根路径上的点完全包含这种颜色, 在 (lca) 打标记, 最后上传标记即可.
只要倍增(lca) 的常数够优秀, 也是能过这道题的.
T3.6808east
先讨论 (a_i) 各不相同的情况,显然一个区间 ([l, r]) 满足要求的充要条件为 (max(a_i) - min(a_i) = r - l), ((l leq i leq r))。
又可以发现 (max - min geq r - l), 移项得 (max - min + l geq r),所以对于每个右端点 (r),需要维护 (max - nin + l) 的最小值以及取到最小值的左端点数。
考虑用两个单调栈分别维护 (max) 和 (min)。对于 (max),维护一个单调递减的单调栈,每次弹栈的时候,需要修改一个区间的 (max),发现这段区间的 (max) 相同,所以其实就是一个区间加操作,维护 (min) 同理,所以用一棵线段树维护即可。
再考虑有 (a_i) 相同的情况,可以发现上面式子变为 (max - min + l + cnt geq r),(cnt) 为区间内不是第一次出现的数的个数,记录 (a_i) 上一次出现的位置 (las[a_i]),那么其实就是一个区间加1的操作,同样线段树上搞一搞就好。
T4.6809不难题
Description
给定 k 行 n 列的矩阵,每行为 (1) ~ (n) 的排列,互相独立且随机。
要求将一个区间 ([L, R]) 的行拉出来合成一行,不能有连续的 (R - L + 1) 个数相同,
求所有区间的方案数之和
Solution
乍一看感觉挺难求的,再一看还是很难求.....
先在每一行末尾加 (n + 1),那么区间 ([L, R]) 满足条件的方案数就转化为 第一次连续出现 (R - L + 1) 次的数为 (n + 1) 的方案数 / ((R - L + 1)!)。
转化之后便比较好设状态了,设 (f[x]) 表示区间 ([L, R]) 中第一次连续出现 (R - L + 1) 次的数为 (x) 的方案数,考虑用 “总方案数” - “不合法方案数”,总方案数就是一堆组合数的乘积。
考虑如何求 (f[x]),如果不需要 (x) 为第一次连续出现的话,(f[x] =) 将每行 (x) 之前的数乱排乘 ((R - L + 1)!),但需要删去 (x) 不是第一个连续出现的情况,设 (y) 表示第一次连续出现 (R - L + 1) 次的数为 y,且要求 (x) 能在 (y) 连续出现 (R - L + 1) 次后连续出现,也就是 ([L, R]) 中 (x) 的位置都要在 (y) 之后,那么对于每个 (y),就是 (f[y] imes) 一堆组合数的积,积表示 (y)连续到 (x)连续之间有多少种不同的排列方案。
固定区间左端点,枚举右端点店铺dp,时间复杂度 (O(k^2n^2)),并过不了,但是注意到题目中每一行的排列独立且随机。也就是说,对于满足条件的 ((x, y)),在只有一行时数量为 (frac{n^2}2),以后每多一行,依然满足条件的概率为 (frac12),所以数量也相应的(/2),所以对于一次左端点固定,右端点移动的过程中,((x, y))的总数是(O(n^2))的。
综上,在每次新加入一行时维护合法 ((x, y)),可以使用链表维护,时间复杂度 (O(nk(n + k)))。
最后答案为 (frac{f[n + 1]}{(R - L + 1)!})