zoukankan      html  css  js  c++  java
  • GMOJ 2020.10.29【NOIP提高A组】模拟

    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)!})

  • 相关阅读:
    分享AWS网站
    centos7划分vlan
    在docker容器上如何实现代码的版本管理
    在docker私有仓库如何查看有哪些镜像?
    centos7下报错: import requests ImportError: No module named requests
    Unity2018.4.7导出Xcode工程报错解决方案
    1.OpenGL mac开发环境搭建记录
    unity 模板测试 详解
    游戏战争迷雾
    Unity 移动平台自己编写Shader丢失问题
  • 原文地址:https://www.cnblogs.com/zhouzj2004/p/13909022.html
Copyright © 2011-2022 走看看