zoukankan      html  css  js  c++  java
  • UR #19

    清扫银河

    如果只进行 1 操作,不难证明存在操作序列的充要条件是将所有 1 边拿出来,所有点的度数为偶数,构造方案使用欧拉回路。

    因为不存在重边,所以进行 1 操作时每个环环长一定大于 2,因此如果存在一个只有 1 操作的合法操作序列,这个序列的最短长度不大于 (lfloor frac{m}{3} floor)

    然后考虑 2 操作能为 1 操作做些什么。

    首先可以发现性质:在一次 2 操作中将集合 (S) 中的点变白、其余点变黑进行翻转,等价于对 (S) 中的每一个点 (x)(x) 变白其余点变黑进行一次翻转。

    那么可以只考虑每次只有一个点翻转的情况。那么每一个点至多翻转 (1) 次。某个点翻转一次会导致与这个点直接相连的所有点 1 边数量的奇偶性产生变化,还会根据当前点度数对当前点 1 边数量的奇偶性产生变化。

    考虑使用 0/1 异或方程描述。设 (f_i) 表示第 (i) 个点是否翻转,(d_i) 表示 (i) 点度数,(p_i) 表示初始态下 (i) 点连接的 (1) 边数量的奇偶性,那么有异或方程:

    [sumlimits_{(u,v) in e}f_v oplus [2 otmid d_u] f_u = p_u ]

    如果该方程有解,注意到如果两个点直接相连,可以把它们的翻转操作合并,所以这部分的最小操作次数上界约为 (lceil frac{m}{2} ceil)。所以只要这个异或方程有解,那么一定存在一种方案在 (m+1) 步内完成操作。

    使用 bitset 优化异或方程组求解,复杂度 (O(frac{Tn^3}{w}))

    通用测评号

    Update On 20200405:在看了 nealchen 的三方做法 后深感被教育于是补充了 (O(n^3)) 做法

    先稍微转化一下问题,认为每个燃料仓容量无限,进行无限次操作,每次等概率随机一个燃料仓将 1 单位燃料填进去,问在所有燃料仓燃料 (geq b) 的时刻期望有多少燃料仓燃料 (geq a)

    根据期望的线性性可以考虑 (1) 号燃料仓的燃料 (geq a) 时存在燃料仓燃料 (< b) 的概率。因为每一个燃料仓的概率显然一样所以乘 (n) 即为答案。

    考虑容斥,强制 (p) 个燃料仓燃料 (<b),选燃料仓方案数为 (inom{n-1}{p}),容斥系数为 ((-1)^{p-1})。此时我们只关心这 (p+1) 个燃料仓,那么可以将剩余的 (n-p-1) 个燃料仓忽略掉,认为只有 (p+1) 个燃料仓。

    考虑强制这 (p) 个燃料仓之后怎么算概率。先把问题抽象一下:初始给出一个序列 (S),每一次在 ([1,p+1]) 的正整数中均匀随机一个数放入序列 (S) 末尾,计算当序列中有 (a)(1)(2 sim p+1) 的出现次数均小于 (b) 的概率。

    枚举 (2 sim p+1) 的出现次数,答案即等于

    [sumlimits_{x_2,x_3,ldots,x_{p+1} in [0,b-1]} frac{(a-1 + sum x_i)!}{(a-1)!prod x_i!} left(frac{1}{p+1} ight)^{a+sum x_i} ]

    后面的部分就是序列中的每一个位置都有 (frac{1}{p+1}) 的概率贡献。而前面的多重排列中 (1) 号元素的数量是 (a-1) 的原因是序列的最后一个元素必须要是 (1),所以仅有 (a-1)(1) 和其余元素进行多重排列。

    熟练的你此时一定已经发现这玩意只和 (sum x_i) 以及 (prod x_i!) 有关,可以写成 EGF 形式。设 (F(x) = sumlimits_{i=0}^{b-1} frac{x^i}{i!},G(x) = F(x)^p),那么答案可以改写为

    [sumlimits_{j=0}^{p(b-1)} frac{(a-1+j)!}{(a-1)!} left(frac{1}{p+1} ight)^{a+j} [x^j]G(x) ]

    如果已知 (G(x)) 那么单个 (p) 的答案可以 (O(n^2)) 计算,问题变为对于所有 (i in [1,n-1])(F(x)^i)

    使用 NTT 优化卷积,复杂度 (O(n^3 log n)) NTT 太暴力了,考虑更进一步优化。

    非卷积的多项式运算优化可以考虑求导,注意到 (F' = F - frac{x^{b-1}}{(b-1)!}),那么 ((F^i)' = iF^{i-1}F' = iF^i-iF^{i-1}frac{x^{b-1}}{(b-1)!}),算出 (iF^{i-1}frac{x^{b-1}}{(b-1)!}) 后对比系数可以直接算。复杂度优化为 (O(n^3))

    前进四

    Update On 20200405:我是不是学了个假的 segmen tree beats???

    有个 (O(n log^2 n)) 的做法,详见楼房重建,然后此题区分度变为卡常数过 50w = =。

    问题是这个做法没有利用到询问后缀的要求。先考虑一个暴力:从后往前扫一遍维护后缀 (min),如果新加入的位置的取值比后缀 (min) 小则答案 (+1) 并更新后缀 (min)。这个做法跟特殊性质有千丝万缕的联系,因为每次扫都一定从序列末尾开始。

    楼房重建的做法相当于对时间扫描线维护序列信息,此时由于沿着数组扫能够利用题目性质,故考虑按照序列下标从大到小扫描线,维护每一个时刻从序列末尾扫到当前位置时的信息。我们需要维护两个信息:一个是时刻的后缀 (min),另一个是时刻的后缀 (min) 被更新过了多少遍。

    注意到对于某一个位置的修改,其对应的是时间轴上的一段区间,故对于一段区间需要支持将大于某个数 (v) 的位置的修改次数 (+1) 并将其值修改为 (v)

    对于仅修改 (geq v) 或者 (leq v) 的位置的问题,使用吉司机线段树。复杂度 (O(n log n))

  • 相关阅读:
    【转】排序总结(总结的非常好)
    [转]C#中使用指针实现高效比较字符串的小技巧
    高斯消元法
    排序算法性能和使用场景总结
    斐波那契数列Log(n)算法
    C#部分方法定义
    杂项记录
    C#指针复习示例zz
    【转】斐波那契数列算法分析
    【转】矩阵乘法
  • 原文地址:https://www.cnblogs.com/Itst/p/uojround19.html
Copyright © 2011-2022 走看看