清扫银河
如果只进行 1 操作,不难证明存在操作序列的充要条件是将所有 1 边拿出来,所有点的度数为偶数,构造方案使用欧拉回路。
因为不存在重边,所以进行 1 操作时每个环环长一定大于 2,因此如果存在一个只有 1 操作的合法操作序列,这个序列的最短长度不大于 \(\lfloor \frac{m}{3} \rfloor\)。
然后考虑 2 操作能为 1 操作做些什么。
首先可以发现性质:在一次 2 操作中将集合 \(S\) 中的点变白、其余点变黑进行翻转,等价于对 \(S\) 中的每一个点 \(x\) 将 \(x\) 变白其余点变黑进行一次翻转。
那么可以只考虑每次只有一个点翻转的情况。那么每一个点至多翻转 \(1\) 次。某个点翻转一次会导致与这个点直接相连的所有点 1 边数量的奇偶性产生变化,还会根据当前点度数对当前点 1 边数量的奇偶性产生变化。
考虑使用 0/1 异或方程描述。设 \(f_i\) 表示第 \(i\) 个点是否翻转,\(d_i\) 表示 \(i\) 点度数,\(p_i\) 表示初始态下 \(i\) 点连接的 \(1\) 边数量的奇偶性,那么有异或方程:
如果该方程有解,注意到如果两个点直接相连,可以把它们的翻转操作合并,所以这部分的最小操作次数上界约为 \(\lceil \frac{m}{2} \rceil\)。所以只要这个异或方程有解,那么一定存在一种方案在 \(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\),选燃料仓方案数为 \(\binom{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\) 的出现次数,答案即等于
后面的部分就是序列中的每一个位置都有 \(\frac{1}{p+1}\) 的概率贡献。而前面的多重排列中 \(1\) 号元素的数量是 \(a-1\) 的原因是序列的最后一个元素必须要是 \(1\),所以仅有 \(a-1\) 个 \(1\) 和其余元素进行多重排列。
熟练的你此时一定已经发现这玩意只和 \(\sum x_i\) 以及 \(\prod x_i!\) 有关,可以写成 EGF 形式。设 \(F(x) = \sum\limits_{i=0}^{b-1} \frac{x^i}{i!},G(x) = F(x)^p\),那么答案可以改写为
如果已知 \(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)\)。
来源:oschina
链接:https://my.oschina.net/u/4290521/blog/4336858