zoukankan      html  css  js  c++  java
  • 讲题泛做

    431D Random Task

    A Trick

    数位 dp 答案怎么统计?用记忆化搜索的时候不用单独处理?要写好多参数啊,咋办啊,有没有不用记忆化搜索的方案啊?
    当然有,从网上看到一个绝妙的统计方法可以直接统计。(例子是在网上抄的,进行了部分拓展和详解。)
    比方统计数字和,拿 (3229) 来讲,你可以分成统计这部分的答案:(0000-0999, 1000-1999, 2000-2999, 3000-3099, 3100-3199, 3200-3209, 3210-3219, 3220 - 3229) 的答案。
    对应到已经计算好的 dp 数组上,就是 (f(4, 0) + f(4, 1) + f(4, 2) + 100 imes 3 + f(3, 0) + 100 imes 3 + f(3, 1) + cdots)(后面都是类似的)
    像这样爆草数位 dp 的统计答案环节即可。

    *2000,考察对题意所求值单调性的观察和证明能力,以及数位 dp 的应用

    给定 (m, k),找到一个最小的 (n) 使得 (displaystylesum_{i = n + 1} ^ {2n}[operatorname{popcount}(i) = k] = m)

    (m le 10 ^ {18}, k le 64, 1 le ans le 10 ^ {18})

    dp 好说,可是之前不是很会统计答案,因此为做一个题现场去学了数位 dp……(见上方 A Trick 部分)

    考虑两个相邻的整数 (n - 1)(n),发现这两个数对应需要统计 (operatorname{popcount}) 的集合的不重合部分只有 ({n})({2n - 1, 2n}),而 (operatorname{popcount}(n) = operatorname{popcount}(2n)),因此 (displaystylesum_{i = n + 1} ^ {2n}[operatorname{popcount}(i) = k]) 是单调不降的,二分答案即可。计算这个东西就是个比较平凡的数位 dp 了。

    486D Valid Sets

    *2000,考察简单树形 dp 有变化的应用。

    给一棵树,点有点权,求树上有多少个子连通块满足极差不超过 (d)

    (n, d, a_ile 2 imes 10^3)

    先考虑如何计算一棵树上的子连通块个数,考虑 dp,设 (f(u)) 为以 (u) 为根的子连通块个数:

    [f(u) = prod_{v in son(u)}(f(v) + 1) ]

    原理也很好想,无非就是每个子节点为根的连通块要么一个都不选,要么任选一个。

    另一个需要注意的问题是如何去重,发现只要限制选择连通块中的最小点权,每次统计答案的时候只统计包含最小点权的连通块,即可保证不重不漏,因此枚举最小点权,每次做一个 dp 并统计答案。

    (f(u, 0/1)) 表示以 (u) 为根的子连通块的总个数/选中了最小点权的子连通块个数,那么 (f(u, 0)) 的转移同上文 (f(u))(f(u, 1)) 可以考虑这样求得:((l, r) 表示当前值域,其中 (l) 为最小值)

    [f(u, 1) = egin{cases}f(u, 0), a_u = l\f(u, 0) - left(prodlimits_{v in son(u)}left(f(v, 0) - f(v, 1) + 1 ight) ight), l < a_u le r\0, a_u < l lor a_u > rend{cases} ]

    第二个转移式考虑计算每个子节点中都不包含最小点权的方案数,然后再用总方案数减去。

    总的复杂度为 (O(nw)),其中 (w) 为值域,也可以通过一开始先对点权排序,只取有效点权做到 (O(n^2))

    1004D Sonya and Matrix

    *2300,无关键性算法,主要考察思维。

    萌萌题,草可是我的实现怎么就是比大家的复杂……

    给定 (t)(t) 个数,问你能否用这些数构造出一个 (n imes m) 的矩阵,满足 (n imes m = t),每个数都使用一次,且在这个矩阵中能找到唯一的一个点,满足其余所有数到这个点的曼哈顿距离都等于这个数。构造一种方案,只输出 (n, m) 和这个点的位置即可。

    先统计每个数的个数 (c_i)

    考虑从 (0) 开始一圈一圈往外加,在顶到矩阵的边界之前,一定有 (c_i = 4i),这里不作证明,设 (x_1) 为第一个满足 (c_i < 4i)(i)

    类似的定义 (x_2) 为第二次顶到边界的数,稍加分析可得 (x_2) 为第一个满足 (c_i < 2(i + x_1) - 1)(i)

    这时取 (x_1) 作为零点的横坐标,(x_2) 作为零点的纵坐标,枚举 (t) 的所有因数,然后 (O(nm) = O(t)) bfs 推一下每个点的曼哈顿距离判断一下就行了,做到了 (O(tsigma_0left(t ight))) 的复杂度,已经可以通过。

    但是这样有的时候找不到答案,比如只存在唯一解而且 (n ll m) 的情况,两次顶到的边界分别是矩阵的对边,因此需要打个补丁:

    考虑求出第三次顶到边界的数 (x_3),这里可以只考虑 (n ll m) 的情况,因为哪怕求出来的不合法因为接下来会再 check 一遍因此不用担心输出不合法解。注意到一旦出现了顶到对边的情况,接下来顶到边界第三次之前一定有 (c_i = c_{x_2})。因此 (x_3) 就是第一个满足 (c_i < c_{x_2})(i)

    p.s:根本就不用 bfs 推曼哈顿距离,可以直接枚举点然后计算曼哈顿距离qq_emoji: tuu,是我菜了……

    762D Maximum path

    *2300,思路不难但主要考验码力(?)的 dp。

    给定一个 (3 imes n) 的棋盘每个位置上有一个权值,求从 ((1, 1)) 走到 ((3, n)) 的所有简单路径上的权值和的最大值。

    注意到 (3) 很小,因此读完题就有了大致思路:

    考虑按经过这三个点的顺序,分上图这十五种情况讨论(((

    感觉应该是正确的,但是以有限的码力实现后可能忽略了几种状态或者转移仍旧 WA on 16(

    按三个点讨论太繁琐啦!有没有什么更好的替代方案呢?

    当然有,考虑每条分界线的通过状态,这样就只有五种不同情况啦:

    比上面那种写法好写一万倍qq_emoji: hanx

    723F st-Spanning Tree

    *2300,考察代码能力(?)。

    给定一个无向图和两个点 (s, t) 和两个值 (d_s, d_t),构造一个生成树满足 (deg(s) le d_s, deg(t) le d_t)

    个人感觉思维难度偏低,最多也就 *1500 的样子,差不多读完题就能切吧(?)。

    显然首先跟 (s, t) 都不着边的边都能一开始能加上全加上,把连成一个联通块的点缩起来之后肯定是一个这样的图:

    只和 (s)(t) 中一个相连的点肯定得全连上,对于中间的点,把 (s)(t) 其中一个的度数连满,然后再判断一下剩下的那个度数是否超过限制就行了。

    可能要注意一些特殊情况比如 ((s, t) in E) 是割边或者图根本就不连通的情况。

    这题不写了……

    677D Vanya and Treasure

    *2300,考察复杂度平衡及证明,代码码力。

    给定一个 (n imes m) 的矩阵和一个参数 (p),每个矩阵上有一个数 (a_{i, j} in [1, p]capmathbb Z),要求找到一条 (1 sim p) 的路径满足这条路径上所有相邻两个数的曼哈顿距离之和最短。

    首先肯定得按数分层从某一层转移到下一层没的说,考虑根号分治。

    • 对于出现次数 (> sqrt {nm}) 的数,显然这样的数只会有 (O(sqrt{nm})) 种,因此只要两层中有一层是这样的数,考虑在上一层进行多源 bfs 处理每个位置到上一个数的最短距离,复杂度显然为 (O(nmsqrt{nm}))
    • 对于出现次数 (le sqrt {nm}) 的数,注意到 (displaystylesum_{c_i le sqrt{nm}}c_i = O(nm)),因此直接暴力枚举相邻两层的数进行转移,考虑其中最大的 (c_i) 也是 (O(sqrt{nm})) 的,因此即便转移发生在所有的数和出现次数最大的这个数之间,总的转移数也是 (O(nmsqrt{nm})) 的。

    这个题也不写了……

    1342E Placing Rooks

    *2300(?),考察第二类斯特林数和组合数的意义应用

    (n imes n) 的棋盘上放 (n) 个车,

    这题真的有 2300 吗……

    因为只有 (n) 个,所以所有的格子都被占领,当且仅当每行都有或者每列都有一个车。

    不妨先假设每行都有且仅有一个车。这时如果有 (x) 列没有车,那么就意味着有 (x) 个车跑到了别的车的正下方,这时这对车就能互相攻击到,可以证明这个条件是充要的。

    (x = 1) 的情况)

    因此有 (k) 对车互相攻击到,也就意味着有 (k) 列是空的,故有 (n - k) 列有车。

    那么划分方案数就是把 (n) 个车划分到 (n - k) 个无区分集合内的方案数,然后选 (n - k) 列随意位置、随意顺序放置这 (n - k) 个集合。

    故答案为 (displaystyle{n race n - k}{n choose n - k}(n - k)!)

    uoj #246 破坏发射台

    给定一个长为 (n) 的环,有 (m) 种颜色,要求相邻两个位置、相对两个位置((n) 为奇数的时候视为没有相对的位置)不能同色,求染色方案数。

    之前我研究过没有相对两个位置的限制时候的问题,还出过完全一致的题,是一个裸的矩阵快速幂:

    考虑先固定第一种颜色,然后设 (f(i, 0/1)) 表示第 (i) 个位置与第一种颜色相同/不同的方案总数,于是有:

    [f(i, 0) = (m - 1)f(i - 1, 1)\f(i, 1) = f(i - 1, 0) + (m - 2)f(i - 1, 1) ]

    也可以多做一步把上面的式子代入下边做成一个广义斐波那契数列,最后的答案就是 (mf(n, 1))

    有了奇数的大方向,偶数考虑在这个基础上魔改一下。

    好在只是状态总数的线性增长而不是加维数,考虑同时处理位置相对的颜色对的染色方案数。

    固定 (1) 号位置和 (dfrac{n}{2} + 1) 号位置的颜色,设 (f(i, 0/1/2, 0/1/2)) 表示前半部分颜色与 (1) 号相同/与 (dfrac{n}{2} + 1) 号相同/都不同,后半部分与 (1) 号相同/与 (dfrac{n}{2} + 1) 号相同/都不同的方案数。

    用与奇数完全相似的方式进行矩阵快速幂即可,就是转移麻烦了亿点点(除去不合法的 (f(i, 0, 0))(f(i, 1, 1)),还有 (7) 种状态,加油勇士!((()。

  • 相关阅读:
    python https请求报错:SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED]
    python打包为exe文件
    文件自定义扫描工具
    pandas 的常用方法
    cisco应用
    Cisco 模拟配置
    python 识别图片上的数字
    OpenSSL
    OpenSSL
    OpenSSL
  • 原文地址:https://www.cnblogs.com/zimujun/p/fanzuo.html
Copyright © 2011-2022 走看看