save

树上的数据结构

附录:

前置知识

树的三种序:dfs 序,欧拉序,括号序。

\(O(n\log n) -O(1)\) LCA,\(O(n) - O(\log n)\) LCA。

点 / 边双连通分量,缩点。

kruskal,boruvka?

目录:

  1. 生成树相关
  2. 链剖分 和 dsu on tree
  3. 点 / 边分治与虚树
  4. 笛卡尔树和 kruskal 重构树。
  5. 动态树相关。

生成树相关

kruskal 和 prim 求最小生成树大家都很熟悉了,这里来讲一讲 boruvka 算法:

boruvka 的算法流程是:每一轮,对于每个点,求出与它不在同一个连通块的点的最小边权。每个连通块选择最小的权值连边。

每次操作至少减少一半的连通块。

设“寻找一个与其相连的最小异连通块”的复杂度为 \(O(f(n))\),总时间复杂度 \(O(nf(n)\log n)\)

当两点之间的边权为一些特殊值时很有用。

例题:

【UOJ176】新年的繁荣

\(n\) 个点,每个点有一个属性 \(a_i\)\(x, y\) 之间的边权为 \(a_x \ \mathrm{and} \ a_y\) ,求此图的最小生成树。

AT3611 Tree MST

\(n\) 个点的树,有一张完全图,其中 \(x,y\) 的边长为 \(\mathrm{dis}(x,y)+w_x+w_y\),求该图的最小生成树。

链剖分

树链剖分用于将树分割成若干条链的形式,以维护树上路径的信息。

重链剖分

重链剖分可以将树上的任意一条路径划分成不超过 \(\log n\) 条连续的链,每条链上的点深度互不相同。

重链剖分还能保证划分出的每条链上的节点 DFS 序连续,因此可以方便地用一些维护序列的数据结构(如线段树)来维护树上路径的信息。

例题:

LOJ6669 Nauuo and Binary Tree

[GXOI/GZOI2019]旧词

长链剖分

长链剖分的重儿子变成了深度最大的子节点。其他和重链剖分一样。

长链剖分后,一个点 \(x\)\(k\) 级祖先 \(y\) 的长链长度 \(\geq k\)

因此,一个点 \(x\) 不断跳跃长链到达根节点,切换长链次数为 \(O(\sqrt {n})\) 级别。

例题:

CF526G Spiders Evil Plan

长链剖分优化 dp

在涉及一些以深度为下标的 dp 转移时,长链剖分可以将这些转移优化成线性。

一般长链剖分优化 dp 的流程是:在 dp 过程中,将重儿子的信息 \(O(1)\)继承,此时所有的轻儿子的信息的下标不会超过重儿子的下标,直接暴力将轻儿子的信息合并到重儿子。

使用指针 \(O(1)\) 继承,由于每条重链都只会暴力统计 1 次,时间复杂度 \(O(n)\)

空间能开大就尽量开大,防止神必原因 RE。

[POI2014]HOT-Hotels 加强版

太经典了。

考虑两辆深度相同的三个点呈什么形状分布,继而设计 dp 状态。

Dsu on tree

Dsu on tree,又称树上启发式合并,适用于离线地对于子树 / 路径的信息进行非常暴力直接地维护。

Dsu on tree 的算法流程如下:

  1. 进行轻重链剖分求出重儿子,在处理询问时先遍历轻儿子,最后将它们的信息撤销。
  2. 遍历重儿子,不撤销信息。
  3. 再遍历轻儿子,加入信息。

一个节点被遍历的次数等于包含于它的轻子树的个数,显然为 \(O(\log n)\) 次,所以总增加 / 撤销的次数为 \(O(n \log n)\)

CF1709E XOR Tree

UOJ #284 快乐游戏鸡

虚树

虚树用来解决给定关键点之间的路径信息。

虚树的构建:将所有点按照 dfs 序排序,实时维护一个从根节点出发的链。加入一个点 \(x\) 时,分类讨论:

  • \(x\) 可以直接加入这条链时或者栈为空,直接加入。
  • 否则,设 \(x\) 和栈顶的 lca 为 \(p\),不断弹出 \(dep_z \geq dep_p\) 的点,并加边。然后将 \(p\) 和栈顶连边后将栈顶设为 \(p\),最后加入 \(x\)

虚树的推论

  • 点集 \(a_1, a_2,\dots, a_k\) 形成的虚树边权和为按照 dfs 序排序后相邻两点的距离之和,也就是 \(\dfrac 1 2(\sum\limits_{i = 1}^{k- 1}dist(a_i,a_{i+1})+dist(a_1,a_k))\)
  • 一个点 \(x\) 到关键点的 lca 深度最小值为其在 dfs 序上的前驱后继取 \(\min\)

例题:

【AHOI2022】钥匙

注意到每个颜色可以分开算贡献。要考虑怎么设计一个点对的匹配贡献才不会不重复计算。

发现每种颜色的钥匙很少,而一次贡献又要一把钥匙匹配一个箱子,可以想到“括号序”的方式, 把钥匙看作左括号, 箱子看作右括号。

对于每种颜色建出虚树,枚举可能的钥匙作为起点,当恰好左右括号匹配时,两端在两个子树内的询问点会有贡献,是一个区间的形式,二维数点扫描线即可。

CF809E Surprise me!

首先需要知道:\(\varphi(xy)= \dfrac{\varphi(x)\varphi(y)\gcd(x,y)}{\varphi(\gcd(x,y))}\) ,然后得到:

\(ans = \sum\limits_{i}\sum\limits_{j}\dfrac{\varphi(a_i)\varphi(a_j)\gcd(a_i,a_j)}{\varphi(\gcd(a_i,a_j))}\times dist(i,j)\)

枚举 gcd :\(ans = \sum\limits_{d} \sum\limits_{t}\mu(t)\dfrac{d}{\varphi(d)}\sum\limits_{dt|a_i}\sum\limits_{dt|a_j} dist(i,j)\varphi(a_i)\varphi(a_j)\)

预处理 \(g_d = \sum\limits_{d|a_i}\sum\limits_{d|a_j}dist(i,j)\varphi(a_i)\varphi(a_j)\) ,可以通过每次剑虚树统计得到。然后再做一遍狄利克雷卷积就是答案。

一个点最多被加入 \(\sqrt n\) 个虚树,时间复杂度 \(O(n \sqrt n \log n)\),实际上远远跑不满。

LGP8147 [JRKSJ R4] Salieri

建出 AC 自动机,对于一个询问 \((S,k)\) 而言,相当于有 \(|S|\) 次从 fail 树上一个点到根的路径加。

对形成的连通块建出虚树,二分答案 \(mid\),相当于询问虚树上有多少个点的权值 \(v \geq \left\lfloor\dfrac{mid}{siz}\right\rfloor\),使用主席树维护。

树分治

静态树分治

树分治用来处理所有路径的信息的问题。

类似序列上的分治找中点,树的中点是什么呢?就是树的重心。

点分治的具体流程如下:找到当前连通块的重心 \(p\)(可以一次树形 dp 求得),统计在这个连通块内经过重心路径的信息。然后将重心删除,对于剩下的几棵子树递归上面的过程。

由于删去重心后剩下的所有连通块大小 \(S'\) 不会超过当前大小 \(\dfrac S 2\),因此分治树的层数最多为 \(\log n\), 设统计经过根的信息的复杂的为 \(f(n)\),总时间复杂度为 \(O(n f(n) \log n)\)

当强制经过某一点的路径信息不好求得时,若维护信息具有可减性,利用容斥的思想,可以先计算这个连通块内所有点对路径的答案,在对删去根后的所有儿子 \(y\), 减去 \(y\) 连通块的答案。此时求得的就是强制经过根节点的答案。

例题

[BJOI2017] 树的难题

预处理每个点到分治中心对应子树的颜色权值。在拼接的时候分颜色是否相同考虑,如果相同还要而外减去对应颜色的权值。

考虑开两棵线段树分别维护与当前点同色 / 不同色的权值。把分治中心的所有儿子按照颜色排序后,相同的颜色对应相同的区间。若为两个颜色的交界处直接把同色的信息合并到异色。这个操作可以用线段树合并来完成。

查询时就是区间 \(\max\),可以直接维护。

时间复杂度 \(O(n \log^2n)\)

[CTSC2018]暴力写挂

将答案式乘 2 变成:\(\mathrm{dis}(x,y)+\mathrm{dep}_1(x)+\mathrm{dep}_1(y) - 2\mathrm{dep}_2(\mathrm{lca}(x,y))\)

考虑点分治,设一个点 \(x\) 的权值为 \(w(x) = \mathrm{dep}(x)+\mathrm{len}(x)\), 其中 \(\mathrm{len}(x)\) 表示 \(x\) 到分治重心的距离。

因为答案还和 \(x,y\) 在第二棵树上的 lca 有关,考虑把分治涉及到的这些点建出虚树,枚举 \(\mathrm{lca}\), 答案就是不在同一个子树内(第一棵树上),而且在 lca 的不同子树内(第二棵树上)的最大值,对于虚树上的点维护最大值和不为最大值颜色的次大值即可。

时间复杂度 \(O(n \log^2 n)\), 瓶颈在于对虚树上的点的 dfn 排序。

[WC2018]通道

现在两棵树变成三棵树了,但是保证边权非负。

我们将对第一棵树进行点分治改为边分治,保证只有两种不同的颜色方便合并。

仍然对第二棵树建出虚树,问题就在于如何维护第三棵树上的点对距离。

我们设一个点对 \((x,y)\) 的“距离” 为 \(val_x +val_y + \mathrm{dis}_3(x,y)\),其中 \(val_x = \mathrm{dep}_1(x)+\mathrm{len}(x)+\mathrm{dep}_2(x)\), 数组的定义和上面的题一样。对于每一个 lca,我们要求不同子树内的 “距离”最大值。

你可能很奇怪为什么我要定义一个距离而不是权值,实际上,由于边权非负,直径的信息是可以合并的。

具体地,设 \(S_1,S_2\) 为两个点集,设它们直径的端点分别为 \((a, b)\)\((c,d)\), 则 \(S_1 \cup S_2\) 的直径只可能是 \(a,b, c,d\) 任意组合后得到的最大值。

查询时就分别把黑色点和白色点的直径端点两个两两拼接取 \(\max\) 即可。

时间复杂度 \(O(n \log^2 n)\)

动态树分治

对于单次全局询问,可以使用点分治。若要修改或者多次询问呢?

将点分治每次的重心按照遍历顺序建立父子关系,可以得到一棵新树,称为点分树。

由于点分治最多进行 \(\log n\) 轮,因此点分树的深度为 \(\log n\) 级别。这意味着我们可以从一个点暴力跳到根节点,通过在每个点维护一些信息,可以方便地将点分治的过程动态化。

以 震波 为例:

给定一棵树,每个点有点权。支持单点修改,或者询问一个点 \(x\) 距离不超过 \(k\) 的连通块的权值和。

对于一个分治重心,维护一棵以到重心的距离为下标的线段树,表示距离为 \(k\) 的点的点权之和。

对于单次询问 \((x,k)\),先统计 \(x\) 作为分治重心的答案,再不断跳父亲 \(fa\),统计 \(fa\) 的连通块内除去 \(x\) 的连通块的信息,也就是距离 \(fa\) 不超过 \(k - dist(x,fa)\) 的点权。

为了做到这点,额外维护每个点的连通块到其分治父亲的线段树,那么在查询时就可以用父亲的总信息减去父亲对儿子的信息。

在修改时,同时修改这两个线段树即可。

时间复杂度 \(O(n \log^2 n)\)

[ZJOI2007] 捉迷藏

保存每个点到分治重心的最大距离和次大距离,拼起来就是答案。 用可删堆保存。

维护每个点到父亲的最大距离,在加入一个点时,先删去对父亲的影响,在再到父亲的距离的堆里面加入,再更新父亲对全局答案的影响。

kruskal 重构树

kruskal 重构树用来解决树 / 图上路径的最值问题。

我们将 kruskal 的过程改写:把边从小到大排序后,若 \((u, v)\) 不连通,我们新建节点 \(p\), 将 $u,v $ 的父亲设为 \(p\),继续操作。这样子得到的一棵树叫做重构树。

一般情况下我们是对边建出的重构树,当然也可以对点进行操作,若要求 \(\leq d\), 就把边 \((u,v)\) 的权值设为 \(\max(w_u,w_v)\) \(\geq d\) 同理。

性质

  1. 一般情况下是是一棵二叉树。

  2. 原图的所有节点是重构树上的叶子节点。

  3. 对于节点 \(u\) 和其父亲节点 \(v\), 满足相同的偏序关系,即父节点的权值总不大于儿子的权值或总不小于儿子节点。因此 \(u \to v\) 上的边权最大 / 最小值为重构树上的 LCA 节点

    求解节点 \(x\) 在经过边权不超过 \(d\) 的边所能到达的连通块,就是在重构树上 \(u\) 的最浅祖先满足其权值 \(\geq d\) 的子树。

[NOI2018] 归程

建出重构树后倍增,就变成了子树最小值。

[IOI2018] werewolf 狼人

人形态只能走 \(\geq L\) 的点权,狼形态只能走 \(\leq R\) 的点权,我们只需要分别对人和狼建出一棵重构树后倍增跳到对应节点后,问题变成了两段区间 \([L_1, R_1]\)\([L_2, R_2]\) 是否有交集。

将节点 \(p\) 在第一棵树上的位置 \(pos_i\) 作为下标按照第二棵树的顺序建出线段树,问题又变成 \([L_2, R_2]\) 中是否存在 \([L_1, R_1]\) 的数,主席树即可。

时间复杂度 \(O(n \log n)\)

BSOJ7688 超级加倍

分别对最大最小建出重构树后,问题等价于在第一棵树上 \(x\)\(y\) 的祖先, 第二棵树上 \(y\)\(x\) 的祖先的 \((x,y)\) 的数量,树状数组统计。

笛卡尔树

笛卡尔树用来解决序列上的最值问题。

笛卡尔树是一棵二叉树,其每一个点有两个键值 \((k, w)\),其中 \(k\) 满足二叉搜索树(中序遍历为原数组)的性质,\(w\) 满足堆(父亲和儿子节点满足相同的偏序关系)的性质的二叉树。

通常对一个序列建笛卡尔树,就是将它的下标作为二叉搜索树的键值,权值 \(val\) 作为堆的键值。

性质

  1. 一定是棵二叉树,而且当点权互不相同时,笛卡尔树唯一。
  2. 笛卡尔树上的节点 \(x\) 的子树对应序列上连续的一段。
  3. 笛卡尔树本质上是一种不平衡的 treap,当权值随机时,其也具有 treap 深度为 \(\log n\) 的性质,因此可以用 treap 来维护笛卡尔树。

构建算法:假设我们要建大根堆的笛卡尔树,实时维护一个栈表示当前最靠右的链节点,其值单调递减。

加入到 \(x\) 时,不断弹出 \(\leq w_x\) 的节点,设最后一个弹出的节点为 \(lst\), 将 \(x\) 的左儿子设为 \(lst\)。设当前栈顶为 \(z\), 将 \(z\) 的右儿子设为 \(x\)。 加入 \(x\)

for(int i = 1; i <= n; ++i) {
    c[i] = read(); 
    while(tp && c[stk[tp]] <= c[i]) lc[i] = stk[tp --]; 
    if(tp) rc[stk[tp]] = i; stk[++tp] = i; 
}
[HNOI2016]序列

对于一次询问 \([l,r]\), 我们找出其最小值位置 \(p\),那么经过 \(p\) 的最小值显然就是 \(a_p\),贡献为 \((p - l+1) \times (r - p+1) \times a_p\),再考虑不经过 \(p\) 的区间。

\(f_i\) 表示以 \(i\) 结尾的所有区间的最小值之和,转移考虑找到在单调栈的栈顶结点 \(j\),显然有 \(f_i = f_j+(i - j) \times a_i\)

对于 \((p,r]\) 这个区间,显然答案可以写成 $\sum\limits_{i = p+1}^{r}f_i - f_{p} $,记一个前缀和数组即可 \(O(1)\)

对于 \([l,p)\) 这个区间同理,我们只用维护后缀和即可。

时间复杂度 \(O(n \log n)\),瓶颈在于区间最值。

CF1117G Recursive Queries

显然,一个区间 \([l,r]\) 的答案为将 \([l,r]\) 中元素建笛卡尔树后,每个点的深度之和(假设根节点深度为 1)

将询问离线按照右端点排序,实时维护 \([1,r]\) 构成的笛卡尔树。

而区间 \([l,r]\) 的笛卡尔树的根就等于这条右链上第一个编号 \(\geq l\) 的点。它的子树就是 \([l,r]\) 的笛卡尔树的右儿子。

现在我们只需要实时维护每个点的深度即可,注意到若当前新插入 \(x\),当前栈顶为 \(p\),则 \(x\) 的左儿子区间为 \([p+1, x - 1]\), 将这些点的深度 + 1 即可,\(x\) 的深度就等于当前栈的元素个数。

当然这样只维护了右儿子,对于左儿子,将数组翻转后再做一次即可。

使用线段树维护区间加,时间复杂度 \(O(n \log n)\)

P5044 [IOI2018] meetings 会议

\(dp_{l,r}\) 表示将编号在 \([l,r]\) 的人聚集起来的最小花费,设 \([l,r]\) 的最大值位置在 \(p\),显然我们不可能在 \(p\) 点举行会议,这样显然不优,则有转移:

\(dp_{l,r} \leftarrow \min(dp_{l,p - 1}+(r - p+1) \times a_p, dp_{p+1,r}+(p - l+1) \times a_p)\)

由于 dp 涉及区间最值的位置,考虑建出笛卡尔树。设询问 \([l,r]\),我们只要求出 \(dp_{l, p - 1}\)\(dp_{p+1,r}\)\(\min\) 。按照上面一个题的套路,后者将整个序列翻转后再求解一遍,于是我们只考虑右儿子也就是 \(dp_{p+1,r}\) 的求解。

设当前在笛卡尔树的 \(p\) 点,设 \(p\) 管辖的范围为 \([l,r]\),实时维护 \(dp_{l, i}, i \in[l,r]\)

假设当前已经把左右儿子的 dp 值求出来了,考虑合并,观察上面的柿子,等价于 \([l,p - 1]\) 整体加上一个一次函数,\([p+1,r]\) 整体加后对一个一次函数取 \(\min\)

\(dp_{l,i}\)\(i\) 的增大单调不降,而且“斜率” 显然要比 \(a_p\) 小,我们可以证明 \([p+1,r]\) 和这个一次函数只有最多一个交点。

由于只有一个交点,被这个一次函数更新的一定是一段区间,于是直接用线段树维护区间加,区间对一个只有一个交点的一次函数取 \(\min\)

实现细节可以对每个区间 \([l,r]\) 保存其端点也就是 \(l\)\(r\) 的值,对一个一次函数取 \(\min\) 时当且仅当这个一次函数在 \(l, r\) 的取值都小于当前取值才更新。

时间复杂度 \(O(n \log n)\)

CF1603F

分类讨论 \(x\) 是否为 0。

\(x = 0\) 时,问题相当于值域在 \([1,2^{k - 1}]\),秩为 \(n\) 的数组数量,第一个位置方案数为 \(2^{k} - 1\),第二个位置为 \(2^{k}-2, \dots\)。以此类推,于是答案是 \(\prod\limits_{i = 1}^{n}(2^k - 2^{i - 1})\)

\(x \neq 0\) 时,对于每个 \(x\) 答案是一样的,不妨假设 \(x = 1\),将 \(x\) 放在第一个位置后再加入 \(n\) 个数。于是设 \(f_{n,r}\) 表示 \(n\) 个数,秩为 \(r\) 的方案,于是有转移:\(f_{n,r} \leftarrow f_{n - 1,r} \times 2^{r - 1}+f_{n - 1, r - 1} \times (2^k - 2^{r - 1})\)

答案即是 \(\sum\limits_rf_{n+1,r}\)

\(F_r(x) = \sum\limits_{n}f_{n,r}x^n\),于是有 \(F_{r}(x) = F_r(x) \times x \times 2^{r - 1}+F_{r - 1} \times x \times (2^k - 2^{r - 1})\),即 \(F_r(x) = x^r \times \prod\limits_{i = 1}^{r}\dfrac{2^k - 2^{i - 1}}{1 - 2^{i - 1}x}\),将 \(F_r(2x)\)\(F_r(x)\) 比较发现 \(F_r(x) = F_r(2x) \times \dfrac{1 - 2^rx}{1 - x}\),提取系数后得到 \(f_n = \prod\limits_{i = 1}^{n}\dfrac{2^{i+r - 1} - 1}{2^i - 1}\)

答案就是 \(\dfrac{1}{2^k - 1}\sum\limits_r \prod\limits_{i=1}^{n-r+1}\dfrac{2^{i+r - 1} - 1} {2^i - 1}\)

CF1726E Almost Perfect

ARC120F / F2

\(f_{n,k}\) 表示在长度为 \(n\) 的序列中选出 \(k\) 个不相邻位置的方案,显然有 \(f_{n, k} = f_{n - 1, k}+f_{n - 2, k - 1}\), 通过简单的生成函数运算发现 \(f_{n,k} = \dbinom{n - k+1}k\)

于是答案可以表示成 \(\sum\limits_{i=0}^{k - 1}f_{m_1, i} \times f_{m_2, k - i - 1}\)。可惜的是,虽然看起来很像范德蒙德卷积,但并不能化简。 于是寄了。

考虑把序列化环,设 \(G(n,i,k)\) 表示长度为 \(n\) 的环中,第 \(i\) 个位置必须选,总共选择 \(k\) 个的方案。

由于环旋转是同构的,于是有 \(G(n, 1, k) = G(n, 2, k) = \dots =G(n, n, k)\),不妨设为 \(F(n,k)\)

\(F(n,k)\) 可以强制将第一个位置设为选择得到通项:

\(F(n, k) = \begin{cases} [k \leq 1] \ \ \ \ \ n < 3 \\ f(n - 3, k - 1) \ \ \ \ \ \ n \geq 3\end{cases}\)

再考虑将环转化成序列,当序列首尾元素没有同时被选择时是肯定是个双射,只用考虑首尾都被选择的情况,此时还剩下 \(n- 4\) 个位置,\(k - 2\) 个数,于是有:

\(ans(n, i, k) = \begin{cases} 0 \ \ \ \ \ \ \ n \or i \or k \leq 0 \\ F(n,k)+f(n - 4, k - 2) \ \ \ \ \ \ i = 1 \\ F(n,k)+ans(n - 4, i - 2, k - 2) \ \ \ \ \ \ i > 1 \\ ans(n, n - i +1, k) \ \ \ \ \ \ \ i > \left\lceil\dfrac n 2 \right\rceil \end{cases}\)

若没有 \(i\) 的约束,展开后就是 \(F(n, k) +F(n - 4, k - 2) + \dots\) ,于是可以预处理下前缀的 \(F\) 后对 \(i\) 分别是奇偶讨论。

CF1753D

CF1732F

BS8187 可重集计数

BS8181 周黑鸭 D

BS8177 进制D / loj510 北校门外的回忆

LG8558 黑暗(Darkness)

LG8559 寻宝(Treasure)

LG8560 约定(Promise)

P5320 [BJOI2019]勘破神机

\(1 \times 2\)\(2 \times 1\) 的骨牌铺满 \(2 \times n\) 的方格的方案为 \(f_{n+1}\),其中 \(f_0 = 0, f_1 = 1\)

\(f_n = \dfrac{\sqrt{5}}5((\dfrac{1+\sqrt 5}2)^n - (\dfrac{1 - \sqrt 5} 2)^n)\)

铺满 \(3 \times n\) 的骨牌方案为 \(g_n = 3g_{n - 2}+2\sum\limits_{k \geq 2}g_{n - 2k}\),将下表除以二,使用简单的特征根解得:

\(g_n= \dfrac{3+\sqrt 3}6(2+\sqrt 3)^n+\dfrac{3 - \sqrt 3}6(2-\sqrt3)^n\),设为 \(f_n = Ax^n+By^n\)

答案是 \(\sum\limits_{n = l}^{r}\dbinom{f_n}k = \dfrac 1 {k!}\sum\limits_{n = l}^{r}f_n^{\underline k}\),利用第一类斯特林数展开下降幂得到:

\(=\sum\limits_{n = l}^{r}\sum\limits_{i= 0}^{k}\begin{bmatrix} k \\ i \end{bmatrix}(-1)^{k - i}f_n^i = \sum\limits_{i = 0}^{k}\begin{bmatrix} k \\ i \end{bmatrix}(-1)^{k - i}\sum\limits_{n = l}^{r}f_n^i = \sum\limits_{i = 0}^{k}\begin{bmatrix} k \\ i\end{bmatrix}(-1)^{k - i}\sum\limits_{n = l}^{r}\sum\limits_{j = 0}^{i}\dbinom i j A^jB^{i - j}(x^jy^{i-j})^n\)

\(=\sum\limits_{i = 0}^{k}\begin{bmatrix} k \\ i\end{bmatrix}(-1)^{k - i}\sum\limits_{j = 0}^{i}\dbinom i jA^jB^{i - j}\sum\limits_{n = l}^{r}(x^jy^{i - j})^n\)

扩域,等比数列求和 \(O(k^2 \log k)\)

UOJ#50 链式反应

将原子裂变的过程建出一棵有根树,要求儿子节点编号大于父亲,且一个点的儿子个数 \(s = c+2(c \in S)\),其中有 \(c\) 个儿子为叶子节点,\(2\) 个儿子任意。

\(f_n\)\(n\) 个点的答案,枚举根的两个儿子可得:\(f_n = \dfrac 1 2\sum\limits_{i}\sum\limits_{j}\dbinom{n - 1}{i+j}\dbinom{n - 1 - i}{j}f_if_j[n - 1 - i - j \in S]\)

\(F' = F^2G+1\),全半在线卷积。

「JOI 2017 Final」准高速电车

贪心,由于 \(B <C <A\),相邻两个快车站之间的最短路一定是全部走 B,在它们之间的列车贪心地先走 A,走到不能走了就只能走 B。模拟即可。


「JOI 2017 Final」JOIOI 王国

二分极差。一个省的选择方案一定是单调不增的,记录两个省的 mx 和 mn,贪心选择。

由于一定存在一整行或一整列被选择的情况,只需要对四个方向都做一遍就是对的。


「JOI 2017 Final」绳

结论题。

首先染色可以在翻折之前就染完,这样一定不劣于边翻折边染色。于是我们就要判断颜色数量为 2 的序列是否合法。

结论:一个序列合法当且仅当 除了首尾颜色连续段外的其他颜色段长度均为偶数。

证明:

  • 充分性:若只剩下两段显然成立。否则将最后一段的长度变为 1,将序列沿倒数第二段中点对折,重复操作直到剩下两段。
  • 必要性:若存在长度为奇数的非首尾段,那么翻折一定不会在这一段进行。而翻折其他段,这个段仍然会有两个异色段相邻,于是不可能剩下两个段。

有了这个结论后,将长度为偶数的段拆成若干个长度为 2 的段,枚举第一段的位置(只有可能是 1 或者 2 开头),对于单个的颜色 \(c\) 答案就是:\(\min_{j \neq i}n - cnt_i - cnt_j +f_{i,j}\),其中 \(f_{i,j}\) 表示长度为 2 的段的颜色分别为 \(i,j\) 的段的个数。

对于每一个 \(j \neq i\) 维护 \(f_{i,j} - cnt_j\) 的最大值。每次只用动态加 \ 删一个桶,时间复杂度线性。


「JOI 2018 Final」寒冬暖炉

贪心选择前 \(k\) 大的空隙即可。

「JOI 2019 Final」画展

按照画框从大到小排序后,按照美观度从大到小加入画,若当前画框能匹配画则加入。

正确性显然。

「JOISC 2018 Day 2」最差记者 3

\(a_i\) 不是 \(a_{i - 1}\) 的倍数,将 \(a_i\) 改成 \((\left\lfloor\dfrac{a_i}{a_{i - 1}}\right\rfloor +1)a_{i - 1}\) 不会影响答案。因此本质不同的 \(a_i\) 只有 \(\log\) 个。于是把 \(a\) 相同的区间缩起来。

模拟队列行进的过程可以发现,一个步伐为 \(a_i\) 的人只会走 \(a_i\) 的倍数距离,且若经过时间为 \(t\),走过的距离为 \(\left\lfloor\dfrac{a_i}t\right\rfloor \times t\)。由于不同的 \(a_i\) 只有 \(\log n\) 个,每一段都是一个区间,于是直接暴力判断即可。

「JOISC 2019 Day1」馕

由于没有什么显然无解的情况,于是猜测所有情况都有解。

考虑怎么贪心,一定是越靠前的位置分给的越多的人越好,设 \(pos_{i,j}\) 表示只考虑第 \(i\) 个人,把整个馕平均分成 \(n\) 份时第 \(j\) 份的结束位置。

枚举每一段,贪心选择未被得到馕的且结束位置最靠前的人。

「JOI Open 2019」汇款

每循环一圈,\(s\) 变成了 \(\dfrac s {2^n}\),模拟 \(\log V\) 轮就好了。

「JOISC 2017 Day 2」门票安排

阴间思维题。

首先把从 \(A \to B\) 的旅程看做要么 \([A,B) + 1\),要么 \([1,n] \ / \ [A,B]+1\),问题就是使得序列的最大值最小。

直接二分最大值,然而不会检验,遂寻求一些性质。

不妨让所有请求都选择 \([A,B)\),设 \(a_i\) 表示当前的数列, \(b_i\) 表示选择一些区间翻转后的答案序列。

  • 性质 1:所有翻转的序列两辆有交。

    说明:若区间无交,显然不翻转不比翻转劣。

  • 性质 2:设所有翻转区间的交集为 \([l,r]\),设 \(t\) 表示 \(a_{l \dots r}\) 中最大的下标,则有 \(b_t \geq \max b_i - 1\)

    说明:可以感性理解为每次翻转都要包含最大的元素,只不过可能需要微调。当 \(l \leq i \leq r\) 时显然成立,否则任意撤销一个翻转区间,答案不变劣。

  • 性质 3:\(t\) 满足 \(a_t = \max a_i\)

    说明:仍然考虑反证法,当 \(l \leq t' \leq r\) 显然成立,设 \(a_t - b_t\) 表示经过 \(t\) 的翻转区间的个数,则有\(a_t - b_t \geq a_{t'} - b_{t'}+1\),得到 \(a_t+b_{t'} \geq b_t +a_{t'} + 1\),与性质 2 矛盾。

根据上面的结论,可以开始二分答案 \(cnt\)。 根据性质 3,可以先找到 \(a\) 序列中的 \(t\)

此时翻转个数 \(num\), 要么等于 \(a_t - cnt\),要么等于 \(a_t - cnt+1\),分别检验。

然后需要将所有 \(l \leq t, r \geq t\) 的区间按需求翻转,从 \(1 \to t\) 从小到大扫描线,若当前翻转了 \(p\) 个区间,则当前的 \(b_i = a_i - p +cnt - p\),若 \(b_i > num\),则不得不贪心地把最靠右的右区间翻转,最后再检验一下 \([t+1, n]\) 是否合法。

结论很抽象,二分答案的过程很奇怪,不愧是你 JOI。

LG7718 「EZEC-10」Equalization

显然转化成长度为 \(n - 1\) 的差分序列,每次可以对一个点单点修改,或者对两个点 \(i, j\) 执行 \(a_i \leftarrow a_i+x, a_j \leftarrow a_j - x\) 的过程。

先考虑最少操作次数怎么求,注意到和为 \(0\) 的一个子集 \(S\) 可以只用 \(|S|- 1\) 次操作即可全部变成 0,而非零子集需要 \(|S|\) 次。于是状压预处理即可得到最少次数 \(cnt\)

接下来分开考虑和为 0 和非 0 子集 \(S\) 的方案,首先 \(cnt!\) 可以最后再乘,先考虑和为 0 的情况,通过经验?我们可以把每次操作的两个点建一条边,于是最后会形成一棵树,任意定根,从叶子节点开始即可唯一还原出这个操作序列。注意实际上这棵树是无根的,于是方案数就是 \(|S|^{|S| - 2}\)

对于和非 0 的情况,任意选择一个点变成当前和的相反数,就变成了和为 0 的情况,于是方案就是 \(2|S| \times S^{|S| - 2} = 2|S|^{|S| - 1}\)

CF938E

问题在序列上是很经典的:预处理每个点包含它的最靠右的线段,然后倍增。

在树上,对于两个点 \((x,y)\) 而言,要么是直接跳到 \(lca\) 的两段次数之和,要么是存在一条经过 \(lca\),且经过 \(x,y\)\(lca\) 的最近点的一个路线,设为直线 \((u,v)\),此时答案要减 1。而是否存在在两棵子树内的点可以看作在 \([L_u, R_u]\)\([L_v, R_v]\) 平面内是否存在 \((dfn_{st}, dfn_{ed})\) 一个点。

二维数点即可。 时间复杂度 \(O(n \log n)\)

2022.11.3

CF487C

显然乘积问题转化成原根,当 \(n\) 不为质数时无解。问题就是 \([1, n - 1]\) 的一个排列,使得前缀和两两不等。

考虑和为 \(n\) 的两两配对,即:\(n - 1, 1, n - 3, 3, \dots\) 这样奇数位置构成了 \(n - 1, n - 2, \dots, \dfrac{n} 2\) 的排列,偶数位置构成了 \(1, 2, \dots, \dfrac n 2\) 的排列。

CF482D

没有翻转儿子是简单的,直接设 \(dp_{x, 0 / 1}\) 表示 \(x\) 子树内,选择了奇数 / 偶数个点的方案,\(O(1)\) 转移。

考虑加上翻转操作后,大多数方案都会 \(\times 2\),但存在特殊情况使得翻转前后答案相同:那就是子树大小全是偶数或者有偶数个奇数的方案,另外开两个数组保存即可。

CF425B

考虑观察合法矩形的特征:每一行要么和前一行相同,要么相反

\(\min(n, m)\) 较小时,直接 \(2^n\) 枚举第一行的选择情况,然后用 bitset 贪心统计。

否则,至少存在一行 \ 一列在最优方案中未被翻转,枚举,再判断。

BS8197

仍然是先观察,三元组 \((x, y, z)\) 的两两距离最大值只可能是深度最大的点与其他点的距离。

枚举最大深度点 \(x\),于是只要 \(x\) 到两个点的距离都不超过 \(k\) 即为合法方案。将点按照深度排序后用点分树统计即可。

Bonus:\(k\) 固定,对所有的 \(c\) 元组 \(2 \leq c \leq n\) 统计答案。

法一:当 \(c\) 不固定时,上面的结论仍然成立,设 \(cnt_x\) 表示距离 \(x\) 不超过 \(k\) 的答案,于是有 \(ans_p = \sum\limits_{i = 1}^{n}\dbinom{cnt_i}{p - 1} = \dfrac{cnt_i!}{(p-1)!(cnt_i - p+1)!}\) ,卷积即可。

法二:考虑 “点数减边数”容斥,一个合法的 \(c\) 元组 \((x_1, x_2, \dots, x_c)\) 一定满足:所有距离 \(x_i\) 不超过 \(\dfrac{k}2\) 的点集的交集是一个联通块。考虑存在分数,于是把边拆成两条边。

对所有点和边分别计算出距离它不超过 \(k\) 的点(边要求距离最远点不超过 \(\dfrac k 2\)),然后点的贡献是 1,边的贡献是 -1,两次卷积。

LG6046 纯粹容器

首先根据 $E(X) = \sum\limits_{i = 0}^{\infty}P(X >i) $ 将期望转成计算 \(n\) 次的概率。将决斗的过程看做缩两个点。

对于单个点而言,找到在其左 / 右边第一个比 \(x\) 大的点 \(p_l, p_r\),则要求不能 \(p_l,p_r\)\(x\) 缩在一起。考虑容斥,\(P(\overline{A \or B}) = 1 -P(A) - P(B) +P(A \and B)\),总方案显然是 \(\dbinom{n - 1}{t}\)\(P(A) = \dbinom{t}{x - p_l}(x - p_l)!(n - 1 - x+p_l)^{\underline{t - x +p_l}}\)\(P(A \and B) = \dbinom{t}{p_r - p_l}(p_r - p_l)!(n - 1 - p_r +p_l)^{t - x -p_r+p_l}\)

CF1299D

1 号点所连接的点只可能是 一个点的联通块 和 两个点的联通块。若选择保留两个点,则会多加入一个简单环。

不存在一条 1 的环异或为 0 相当于所有简单环构成了一个线性基。

观察到 \(\log_2 w = 5\),通过搜索发现,大小为 5 的线性基最多有 400 个。于是考虑直接把线性基加入 dp 状态里面:设 \(dp_S\) 表示目前 1 号点所在的连通块内线性基为 \(S\) 的方案。

先对所有与 1 相连的连通块计算出线性基,若已经存在异或为 0 的路径,则只能全部断开,否则可以将 1 号点线性基和当前线性基合并。通过预处理 \(400^2\) 对线性基的合并,时间复杂度 \(O(400^2 \times 5^2 +400n)\)

CF804D

最长路径要么是两个连通块分别的直径,要么是两个不在同一个连通块的点到该连通块直径端点最大值,设为 \(dis_i\)。将 \(dis_i\) 排序后,启发式合并即可。

LG3412

\(f_x\) 表示 \(x\) 走到其父亲的期望长度,有 \(f_x = \dfrac{1}{deg_x}+\dfrac{1}{deg_x}\sum\limits_{y \in son_x}f_y+f_x+1\),发现\(f_x = deg_x+ \sum\limits_{y \in son_x}f_y\),于是直接考虑每个点作根节点的答案,计算出每条边的贡献。

LG7962

简单的推导可知:\(ans = (\sum\limits_{i}a_i)^2 -n(\sum\limits_ia_i^2)\)。并且题目所给的操作方式就是交换任意两个差分数组的值。

发现数据范围不大,直接模拟退火能得到 88 分的高分!

正解考虑差分数组的单谷性,答案的差分数组一定是先递减,再递增的,于是将差分数组排序后从小到大加入,这个值一定是放在首尾的。设 \(dp_s\) 表示当前和为 \(s\) 时最小的平方和, 注意到非零的 \(d\) 只有 \(\min(n,a )\) 个,\(O(na^2)\) 转移即可。

P3750 [六省联考 2017] 分手是祝愿

\(k = 0\) 时,由于低位不会对高位造成影响,直接从高到低贪心熄灭即可。 设执行次数为 \(cnt\)

而令人惊讶的是,直接输出 \(cnt\) 有 80 分的高分!

\(cnt < k\) 时,直接输出 \(cnt\) 即可。 否则要计算出从 \(cnt\) 次到 \(k\) 次的期望操作次数。

注意到操作是线性无关的,这意味着一定是按照从高到低的顺序依次熄灭。设 \(dp_t\) 表示从还有 \(t\) 盏亮着的灯到 \(t - 1\) 盏的期望操作次数,转移:\(dp_t = \dfrac{t}{n} +\dfrac{n - t}{n}(1+dp_{t+1}+dp_t)\),即 \(dp_t = 1+\dfrac{n - t}{t}+\dfrac{n - t}tdp_{t+1}\),答案就是 \(\sum\limits_{i = k+1}^{cnt}dp_i\)

CF605E Intergalaxy Trips

\(dp_i\) 表示 \(i\)\(n\) 的最小期望天数,转移考虑枚举下一个点 \(j\),满足 \(dp_j < dp_i\),且对于 \(dp_k < dp_j\)\(k\) 是关闭的,则 \(dp_i = \sum\limits_{dp_j < dp_i}p_{i,j}dp_j\prod\limits_{dp_k < dp_j}(1 - p_{i,k})+1\)

但上面计算的是与 \(i\) 相连的至少一条边开启的方案,还需要除以至少一条边开启的概率 \(P_i = 1 - \prod\limits_{dp_{k}}(1 - p_{i,k})\)

注意到 \(dp_i\) 只能由 \(dp_j <dp_i\)\(j\) 转移,于是类似 dijkstra 的思想转移即可。

2022.11.4

[AGC030F] Permutation and Minimum

\(2n\) 个位置全是 -1 时,将其看做括号序列的模型:一个长度为 \(2n\) 的括号,其中下标代表相应的值,一个匹配的左右括号 \((x,y)\) 表示将 \(x,y\) 分在一组,不难发现答案为 \((\dbinom{2n}n - \dbinom{2n}{n - 1})n!\)

否则,匹配的两个位置有三种情况:都为 -1;一个为 1,一个为 -1;都不为 -1。

设都为 -1 的匹配有 \(cnt\) 个,最后答案乘上 \(cnt!\) 即可。

类似的思想,忽略掉都不为 -1 的位置,将不为 -1 的值看做方括号,为 -1 的看做圆括号,规定不能出现方方括号匹配的情况。设计 dp 状态为 \(dp_{i,j,k}\) 表示从 \(2n\) 从大到小考虑到 1,当前还有 \(j\) 个圆括号, \(k\) 个方括号。转移分类讨论当前值的出现情况:

  • 若其是都不为 -1 的匹配,忽略。
  • 若其未在原序列出现:
    • 作为左圆括号,匹配一个右圆括号:\(dp_{i - 1, j - 1, k} \leftarrow dp_{i,j,k}\)
    • 作为左圆括号,匹配一个右方括号:\(dp_{i - 1, j, k - 1} \leftarrow dp_{i,j,k} \times k\)
    • 作为一个右圆括号:\(dp_{i - 1, j+1, k} \leftarrow dp_{i,j,k}\)
  • 若其在原序列中出现过:
    • 作为左方括号,匹配右圆括号:$dp_{i - 1, j - 1, k}\leftarrow dp_{i,j,k} $
    • 作为右方括号:\(dp_{i - 1, j, k+1}\leftarrow dp_{i,j,k}\)

LG3991

平衡树维护 \(3 \times 3\) 的矩阵即可。

LG3343

证明一下提示中的结论:

\(n\)\([0,1]\) 之间的随机变量 \(x_1, x_2, \dots, x_n\),其第 \(k\) 小的期望为 \(\dfrac{k}{n+1}\)

先求出最大值的期望,对于一个确定的 \(x\),一个变量小于等于 \(x\) 的概率为 \(x\),从 \(n\) 个数中选出这个最大值的方案有 \(n\) 个,于是有:

\[E(mx) = n \times \int_0^1 x \cdot x^{n - 1} dx = \dfrac{n}{n+1} \]

同理 \(E(mn) = \dfrac{1}{n+1}\)

\(k\) 大的方案就是:

\[\dbinom{n - 1}{k - 1} \times n \times \int_0^1 x^{k - 1} \cdot x \cdot(1 - x)^{n - k} = \int_0^1 x^k(1 - x)^{n - k} \]

根据分部积分法,设 \(u = \dfrac{x^{k+1}}{k+1}, v = (1 - x)^{n - k}\),其等于:

\[(uv)|_0^1 + \int_0^1 \dfrac{x^{k+1}}{k+1}(n - k)(1 - x)^{n - k-1} \]

因为 \((uv)|_0^1 = 0\),于是答案等于

\[\dfrac{n - k}{k+1}\int_0^1x^{k+1}(1 - x)^{n - k - 1} \]

\[a_k = \int_0^1x^{k}(1 - x)^{n - k} \]

则有 \(a_k = a_{k+1} \times \dfrac{n - k}{k+1}\)

又因为 \(a_n = \dfrac{n}{n+1}\),故 \(a_k = \dfrac{i!(n - i)!}{(n+1)!}\),因此期望为 \(a_k \times n \times \dfrac{n - 1}{k - 1} = \dfrac{k}{n+1}\)

拓展:\(\Gamma\) 函数和 \(\Beta\) 函数:

\[\Gamma(x) = \int_0^{+\infty}t^{x - 1}e^{-t}dt \\ \Beta(x,y) = \int_0^{1}t^{x - 1}(1 - t)^{y - 1}dt \]

有结论:

  • \(\Gamma(1) = 1\) 且 $\Gamma(x+1) = x\Gamma(x) $,即 \(\Gamma(x) = (x - 1)!\)
  • \(\Beta(x,y) = \dfrac{\Gamma(x)\Gamma(y)}{\Gamma(x+y)}\)

有了结论之后就很简单了,设 \(dp_{S,i}\) 表示当前已经使得点集 \(S\) 联通,且已经连了 \(i\) 条边的方案,答案就是 \(\dfrac{1}{m+1}\sum\limits_{i = 0}^{m} \dfrac{\binom{m}{i} - dp_{all,i}}{\binom{m}i}\) ,转移 \(dp_{S,i} = \dbinom{cnt_S}2 - \sum\limits_{j \leq i} \sum\limits_{T \subset S}dp_{T,j} \dbinom{cnt_{S /T}}{i- j}\)

LG3239

\(f_{i,j}\) 表示考虑到前 \(i\) 张卡牌,已经打出 \(j\) 张的概率,则 \(f_{i,j} = f_{i - 1, j - 1}(1 - (1 - p_i)^{k - j+1})+f_{i - 1, j}(1-p_i)^{k - j}\)

答案就是 \(\sum\limits_{i}d_i\sum\limits_{j}f_{i - 1, j}(1 - (1 - p)^{k - j})\)

LG3352

考虑 \(E(a_i) = \max a_i - \sum\limits_{j}P(j >a_i)\),于是需要计算权值小于 \(j\) 的方案。

枚举 \(v\),将 \(< v\) 的值设为 \(0\)\(\geq v\) 的值设为 1,每次操作可以看做把全 0 连续段缩一部分,设 \(dp_{k,l,r}\) 表示经过 \(k\) 次操作后,满足 \(a_l = a_r = 1, \forall i \in(l,r),a_i = 0\) 的方案。

转移有考虑该次操作是否包含区间,有 \(dp_{k,i,j} \leftarrow dp_{k - 1, i,j} \times(\dfrac{i(i+1)}2 +\dfrac{(n - j+1)(n - j +2)}{2}+\dfrac{(j - i)(j - i - 1)}{2})+\sum\limits_{l < i}dp_{k - 1, l,j}\times l+\sum\limits_{r>j}dp_{k - 1, i,r}\times(n -r+1)\) 可以前缀和优化为 \(O(n^3)\)。每次枚举 \(v\),将初始相邻为 1 的位置 dp 初始化,时间复杂度 \(O(n^4)\)

发现每次 dp 转移都是一样的,只有初始值有变化,于是预先把所有的 dp 累加后再做一次 dp 即可。

答案即是 \(\sum\limits_{l = 0}^{n+1}\sum\limits_{r = l+2}^{n}\sum\limits_{k = l+1}^{r - 1}dp_{m,l,r}\)

LG1758

考虑 \(\sum a_i^2\) 的组合意义:选两次,两次方案均相同的方案。

于是设 \(dp_{i,j,k}\) 表示第一次选球,在上管道选了前 \(i\) 个,在下管道选了前 \(j\) 个;第二次在上面选了 \(k\) 个,下面选了 \(i+j - k\) 的方案。转移显然。

[AGC013E] Placing Squares

首先有暴力 dp :\(dp_i = \sum\limits_{j < i\and!vis_j}dp_j(i - j+1)^2\)。发现是两次的,不能直接优化。

考虑把这个问题转化成神必组合意义:在长度为 \(n\) 的序列中插入若干个隔板,一些特定的位置不能插隔板,然后需要在每个相邻的隔板中选出一个白球,一个黑球(可以重合)的方案。

\(dp_{i,0 / 1/ 2}\) 表示当前考虑到前 \(i\) 个位置,当前 \(i\) 所在连通块选择了 0 / 1 / 2 个球的方案,转移分当前位置是否被限制:

  • 若当前位置未被限制,则有:
    • \(dp_{i+1,0} \leftarrow dp_{i,0}+dp_{i,2}\)
    • \(dp_{i+1,1} \leftarrow dp_{i,1}+2dp_{i,0}+2dp_{i,2}\)
    • \(dp_{i+1,2}\leftarrow 2dp_{i,2}+dp_{i,0}+dp_{i,1}\)
  • 若当前位置被限制,则有:
    • \(dp_{i+1, 0} \leftarrow dp_{i,0}\)
    • \(dp_{i+1,1} \leftarrow dp_{i,1}+2dp_{i,0}\)
    • \(dp_{i+1,2} \leftarrow dp_{i,2}+dp_{i,1}\)

矩阵快速幂即可。

CF913F

竞赛图缩点后会形成一条链,考虑枚举这条链的末尾。

\(dp_n\) 表示 \(n\) 个人的期望值,则有:\(dp_n = \sum\limits_{i = 1}^{n}c_id_{n,i}(dp_i+dp_{n - i}+\dbinom i 2+\dbinom {n - i}2)\),即 \(dp_n = \dfrac{\sum\limits_{i = 1}^{n - 1}c_id_{n,i}(dp_i+dp_{n - i}+\dbinom i 2 +\dbinom {n - i}2)+c_nd_{n,n}\dbinom n 2}{1 - c_nd_{n,n}}\)

其中· \(d_{n,i}\) 表示从 \(n\) 个点中选出 \(i\) 个出度为 0 的点概率,\(c_i\) 表示 \(i\) 个点组成强联通分量的概率 。

\(d\) 的转移是简单的,只用枚举 \(n\) 号点的连通情况:\(d_{n, i} = d_{n - 1, i - 1} \times p^{n - i}+dp_{n - 1, i} \times (1 - p)^i\)

\(c\) 的转移同理:\(c_i = 1 - \sum\limits_{j < i}c_jd_{i,j}\)

\(O(n^2)\)

CF1067D

由于 \(a_i < b_i\),最优策略一定是成功一次后,一直选择 \(p_ib_i\) 最大的,设 \(w = \max p_ib_i\),则考虑第一次成功之前的期望:设 \(dp_n\) 表示剩下 \(n\) 秒的期望收益,则有:\(dp_n = \max \limits_{i} (p_i \times (a_i+(n - 1)*w)+(1 - p_i)dp_{n - 1})\)

发现有乘积项,套路地拆成斜率式的形式:\(dp_t = p_i((n - 1) \times w - dp_{t - 1})+p_ia_i+ dp_{t - 1}\)

于是可以看作 斜率为 \(dp_{t - 1} - (n - 1) \times w\) 的直线截点 \((p_I, p_ia_i)\)。 于是先建一个上凸包。每次直接二分可以做到 \(O(m\log n)\)

但由于 \(m\) 太大,我们猜测 \(g_t = dp_{t} - t \times w\) 随着 \(t\) 的增大单调不增,这样每个在凸包上的点对 dp 的转移就是一段区间。

由于 \(g_t - g_{t - 1} = dp_t - dp_{t - 1} - w\),每次的收益一定比不会大于 \(w\),于是单调性得证。

于是直接对每个点扫一遍,考虑固定一个 \(i\)\(g_t\) 的变化:\(g_t = g_{t - 1} - p_ig_{t - 1} - w\),也是一个一次函数,于是直接倍增预处理一下函数的复合,再从大往小 check 即可。 时间复杂度 \(O(n \log n)\)

CF986E

一开始想复杂了,以为 gcd 要用莫反来搞,但其实是乘积,对于每个素因子分开考虑就好。

将询问差分后,设 \(V = p_1^{\alpha_1}p_2^{\alpha_2}\dots\),变成询问树上一段前缀中出现次数为 \(cnt\) 的个数,贡献为 \(p_k^{\min(cnt, \alpha_k)}\)。由于 \(\alpha_i, cnt \leq 23\),直接开个桶就好了,对于每个素因子 \(O(\log_PV)\) 算一下就好了。

CF1605F

先考虑一个固定的序列是否是好的:显然,记录当前 \(\mathrm or\) 前缀和 \(S\),每次选择两个 \(x, y\) 满足 \(x | S = y |S\),拼在首尾,再更新 \(S\)

发现这个构造并不能直接对好序列计数,但是可以考虑利用这个操作搭建起好序列和坏序列的桥梁,然后通过容斥计算好序列。

一个坏序列一定存在一个极长的好序列,满足剩下的未被加入的数在除去 \(S\) 中为 1 位后两两不同,且非 0。

但有一些细节:当一个好序列长度为奇数,且中间的数出现了前面没有出现过的二进制,这个序列不会映射到任何一个好序列。于是不能称这个序列是好的。

\(h_{n, m}\) 表示 \(n\) 个数,其二进制的并的大小恰好为 \(m\) 的方案,其可以简单二项式反演得到:\(h_{n, m} = \sum\limits_{i \leq m}(-1)^{m - i}\dbinom{m}i(2^{i})^n\),设 \(f_{n, m}\) 表示合法的长度为 \(n\) 的值为 \(m\) 的序列个数, \(g_{n,m}\) 为非法个数,则根据上面的过程,枚举极长的合法序列和合法序列的二进制并的大小,有:\(g_{n, m} = \sum\limits_{i < n}\sum\limits_{j < m}\dbinom{n}i\dbinom m jf_{i,j}(2^{j})^{n - i} r_{n - i, m - j}\) ,其中 \(r_{i,j}\) 表示长度为 \(i\) 的序列,值在 \([1,2^j)\) 且两两不同,并为全集的方案。同样可以二项式反演得到。

然后 \(f_{n, m} = all_{n, m} - g_{n,m}\),答案就是 \(\sum\limits_{i}f_{n,i}\dbinom m i\)。 如果当 \(n\) 是奇数,还需要而外加上长度为 \(n - 1\) 的合法序列的数量。

P4707 重返现世

题目即求 \(E(\mathrm{kthmax}(S))\),发现 \(k \geq n - 10\), 先令 \(k \leftarrow n - k\) 变成求第 \(k\) 小的。根据 \(\min - \max\) 容斥的扩展形式,有:

\(E(\mathrm{kthmin}(S)) = \sum\limits_{\emptyset \subset T \subseteq S}(-1)^{|T| - 1} \dbinom{|T| - 1}{k - 1}E(\max(T))\)。而对于一个固定的 \(T\)\(E(\max(T)) = \dfrac{m}{\sum\limits_{x \in T}p_x}\)

发现 \(m \leq 10000\),于是考虑直接把 \(\sum p\) 记到 dp 里面:设 \(dp_{i, j, s}\) 表示当前考虑到前 \(i\) 个数,目前的 \(k = j\)\(\sum\limits_x p_x = s\) 的容斥系数之和,答案就是 \(\sum\limits_{i} dp_{n, k, i} \times \dfrac{m} i\)

考虑转移,不选择 \(i\) 就是 \(dp_{i - 1, j, s}\), 否则根据 \(\dbinom{|T| - 1+1}{k - 1} = \dbinom{|T| - 1}{k - 1}+\dbinom{|T| - 1}{k - 2}\),于是 \(dp_{i, j, s} \leftarrow dp_{i - 1, j, s}+dp_{i - 1, j - 1, s - p_i} - dp_{i -1, j, s - p_i}\)

CF1515E Phoenix and Computers

最后呈现的形式一定是若干个间隔为 1 的连续段, 设其 EGF 为 \(F(x)\),答案就是 \(\sum\limits_{k} [x^{n - k + 1}]F^k\)

对于单个连续段而言,其方案数为 \(2^{i - 1}\),意思是随便选择一个当作第一个开的,每次可以选择左边或者右边。

然后直接卷起来即可,时间复杂度 \(O(n^3)\)

P5279 [ZJOI2019]麻将

能胡牌当且当存在 7 个对子或者 4 个面子 + 1 个对子。

考虑从小到大加入牌,只保留未胡牌的状态,考虑设计 \(dp_{0 / 1,j, k}\) 表示当前是否存在雀头, 有 \(j\) 个形如 \([i - 2, i - 1]\) 的对子, \(k\)\(i - 1\) 时,已经存在的最多的面子个数。注意到 \(j \geq 3\) 时能直接组成 2 个刻子, \(k \geq 3\) 时能直接组成 1 个刻子,因此 \(j, k < 3\)

每次考虑加入 \(cnt\)\(i\)。 那么会优先拼 \([i - 2, i - 1, i]\), 然后拼 \([i - 1, i]\),最后若剩下 \(\geq 3\) 个直接拼成 \(i, i , i\)

于是可以像矩阵那样保存答案。 同时,若 \(cnt \geq 2\),还可以先用 2 张 \(i\) 组成雀头后更新 \(dp_1\)

对于 7 个对子的情况,直接同一个变量表示当前对子的数量 。然后用 dp of dp 转移,bfs 一下状态个数不多。

然后设 \(dp_{i, u}\) 表示目前已经抽了 \(i\) 张牌,当前在自动机上的 \(u\) 点的方案,可以 \(O(2092 \times n \times 4n)\) 转移。

最后答案就是 \(\dfrac{1}{(4n - 13)!}\sum\limits_{i}\sum\limits_u dp_{i, u} \times i !\times (4n - 13 - i)!\)

P5406 [THUPC2019]找树

P7468 [NOI Online 2021 提高组] 愤怒的小 N

一年前..折戟成沙..今天..30min内...我不再是以前那个我了

把 a 看做 0, b 看做 1。后 \(2^{n - 1}\) 的序列是由前 \(2^{n - 1}\) 在最高位,的容易发现该序列的通项

BS8240

对于一条边连向的两个点,我们只关心他们颜色相同与否。于是可以考虑把 \(n\) 个点分成若干集合,每个集合内部颜色相同,集合之间没有区别。不难发现这就是贝尔数的定义。

注意到 \(bell_{12} = 4213597\),于是当 \(n \leq 12\) 时直接搜索 \(n\) 个点的划分,再乘上 \(k^{\underline{cnt}}\) 即可。

再考虑一棵树的情况,容易设计 $dp_{x,i} $ 表示 \(x\) 颜色为 \(i\) 的总权值然后 \(O(nk)\) 转移,由于颜色之间没有区别,每个 \(i\)\(dp_{x,i}\) 都是一样的,所以可以 \(O(n)\)

于是就 70 了。

再考虑最后几个点,发现非树边最多只有 \(10\) 条,类似上面的思路,随便找一棵生成树后,对于每条非树边,直接搜索确定一点的颜色,此时设 \(dp_{x,i}\) 表示选择第 \(i\) 种颜色的方案(当 \(i = 0\) 时是未选择的 \(k - cnt\) 种颜色),最后把根据当前点的颜色选择,将其所对应的非树边答案累加。

于是复杂度就是 \(O(bell_{10}nk)\),因为 \(bell_{10}\) 是 1e5 级别,算出来只有 1e8,但会被卡常。

题解的一个解决方案是将 1 度点删去,2 度点将其贡献累加到所连向的两个点。这样每个点度数 \(\geq 3\),于是总点数减少,跑得飞快。

BS8241

建出括号树,对于一个询问 \(x, y(x<y)\) 而言,一定是不断跳,跳到其 lca 的两个儿子,要么直接从 lca 处转换括号,要么从同层括号之间单向移动。

于是只用预处理一个左 / 右括号到其父亲的 左 / 右括号的最小步数,显然可以在建树时用一个 \(2 \times 2\) 的矩阵表示转移。然后大力分讨就 over 了。

还有小清新的直接倍增写法,就是直接对每个点预处理跳 \(2^j\) 能到达的最左 / 最右点,一个跳 $2^j $ 的能到达的最左点要么是最靠左的 \(2^{j - 1}\),要么是最靠右的 \(2^{j - 1}\)。询问类似上面的做法,从两个点开始跳,一直跳到 lca 即可。

BS8236

硬核推柿子题。

首先考虑求出一个点的期望深度,设 \(d_x\) 表示 \(x\) 的期望深度,\(b_x\)\(a_x\) 的前缀和,有转移 \(d_x =\dfrac{\sum\limits_{i = 1}^{x - 1}a_i(d_i+c_i+c_x)}{b_{x - 1}}\),可以通过分离变量做到 \(O(n)\)

对于询问 \(x,y\),我们想要对于每个 \(l \in [1, x]\),计算出 \(l\)\(x,y\)\(\mathrm{lca}\) 的概率,答案就是 \(d_x+d_y -2\sum\limits_{l}P_ld_l\)

假设 \(x<y\),直接枚举 \(x - y\) 的路径上经过的点集 \(S_{x,y}\),会发现其由两部分组成:在 \((l,x)\) 上的点可以在 \(l - x\) 的路径上,也可以在 \(l - y\) 上;对于 \((x,y)\) 的点,只能在 \(l - y\) 上,然后 开 幕 雷 击:

\(P_l =\dfrac{a_l^2}{b_{x - 1}b_{y - 1}} \sum\limits_{S_1 \subseteq (l, x)}\sum\limits_{S_2\subseteq (x,y)} \prod\limits_{i \in S_1}\dfrac{2a_i}{b_{i - 1}}\prod\limits_{i \in S_2} \dfrac{a_i}{b_{i - 1}}\)

解释一下:本质上就是一堆点,其 \(\dfrac{a_{p_{i - 1}}}{b_{p_i - 1}}\) 的乘积,只不过把 \(l, x, y\) 的贡献单独处理了,这个柿子在 \(x = l\) 时不成立,需要特殊处理。

然后将 \(\sum\limits_{S_1 \subseteq (l,x)}\prod ...\) 看成每个点选或不选:\(\prod\limits_{i = l+1}^{x - 1}(1+\dfrac{2a_i}{b_{i - 1}}) = \prod\limits_{i = l+1}^{x - 1}\dfrac{a_i+b_{i}}{b_{i-1}}\),右边 \(\prod\limits_{i = x+1}^{y - 1}\dfrac{b_i}{b_{i - 1}} = \dfrac{b_{y - 1}}{b_x}\)

最后的答案就是 \(d_x+d_y - 2\sum\limits_{l = 1}^{x}d_l \times \dfrac{a_l^2}{b_xb_{x - 1}}\prod\limits_{i = l+1}^{x - 1}\dfrac{a_i+b_{i - 1}}{b_{i - 1}}\)。预处理 \(\dfrac{a_i+b_{i - 1}}{b_{i - 1}}\) 的前缀积即可。

BS8237

题意就是划分成两个公差相同的等差数列(可以有一个为空),直观感受一下,这个公差不会太大。

为了方便确定公差的范围,我们不妨将公差 \(d\) 的上界和下界写出来,并枚举首项 \(b\)

最少的操作次数 \(mn = \dfrac{\frac{n(n-1)}{2}d+bn - \sum a_i}{2}\)\(mx = \dfrac{a_{mx} \times n - \sum a_i}{2}+2n\),由于 \(mn \leq mx\),最后发现 \(nd \leq 1e6\)

这意味着我们可以直接暴力枚举 \(d \in [-\dfrac{lim}n, \dfrac {lim}n]\),然后再花 \(O(n) - O(n \log n)\) 的时间得到让一段前缀 / 后缀变成公差为 \(d\) 的等差数列的答案,然后用 \(pre\)\(suf\) 拼起来。

\(c_i = a_i - (i - 1) \times d\),那么对于一个首项 \(b\),对于 \(c_i - b \leq 0\) 的贡献而言,若 \(b - c_i\) 为偶数,就可以一直进行 +2 操作,次数就是 \(\dfrac{b - c_i}2\),否则需要加到 1 后减去 1,贡献就是 \(\dfrac{b+3 - c_i}{2}\);对于 \(c_i - b > 0\) 的贡献就是 \(c_i - b\)

注意到这类似带权中位数问题,对于 \(c_i \leq b\),贡献可近似看做 \(\dfrac{b - c_i}2\)\(c_i > b\) 就是 \(c_i - b\)。根据数学??积累可知:\(b\)\(c[n - \left\lceil \frac n 3\right\rceil+1]\) 取到,由于奇偶性的问题,还需要代入该值 -1 检验。

考虑动态维护这个过程,我们需要动态维护前 \(n - \left\lceil \frac n 3\right\rceil+1\) 的奇 / 偶个数以及和,后 \(\left\lceil \frac n 3\right\rceil\) 的个数以及和就可以 \(O(1)\) 计算答案了。

用对顶堆时刻维护该过程,时间复杂度 \(O(nd \log n)\)

2023.1.12

CF1392H ZS Shuffles Cards

首先需要读懂题意,每次重新抽牌时 \(S\) 是不会变的,且 joker 不会被抽走。

考虑 dp,设 \(dp_{i, j}\) 表示当前卡牌中有 \(i\) 张牌,\(|S| = j\) 的方案数。每种卡牌可以分为三类:只在牌堆中出现的 \(n - j\) 张;只在 \(S\) 中出现的 \(n - i\) 张;在牌堆和集合都出现的 \(i+j - n\) 张的期望抽卡次数。

转移显然:\(dp_{i,j} = 1+\dfrac{n -j}{i+m}dp_{i-1, j+1}+\dfrac{i+j-n}{i+m}dp_{i-1,j}+\dfrac{m}{i+m}dp_{n, j}\)

答案是 \(dp_{n, 0}\)

\(dp_{i,n}\) 特殊转移,有 \(dp_{i,n} = 1+\dfrac{i}{i+m}dp_{i - 1, n}\)

不能直接转移,高斯消元复杂度太高,考虑将每个数 \(dp_{i, j}\) 写成关于 \(dp_{n, j}\) 的一次函数或许可以 \(O(n^2)\),但无法优化。

参考鱼大的思路,先换元 \(a = n - j, b = i+j - n\),变为 \(dp_{a,b} = 1+\dfrac{a}{a+b+m}dp_{a-1,b}+\dfrac{b}{a+b+m}dp_{a, b - 1}+\dfrac{m}{a+b+m}dp_{a, n-a}\),答案还是 \(dp_{n,0}\)。好处是转移只改变了一个项

\(a = 0\) 时:\(dp_{0, b} = 1 + \dfrac{b}{b+m}dp_{0, b - 1}\),解得 \(dp_{0, b} = \dfrac{m+1+b}{m+1}\)

然后考虑第一个柿子,代入 \(b +1\) 得:\(dp_{a, b+1} = 1 +\dfrac{a}{a+b+1+m}dp_{a-1, b+1} +\dfrac{b+1}{a+b+1+m}dp_{a, b }+\dfrac{m}{a+b+1+m}dp_{a, n - a }\)

消去 \(dp_{a, n - a}\) :将柿子写成关于 \(dp_{a, b} - dp_{a, b - 1}\) 的形式,也恰好能完全凑成:\((a+b+m+1)(dp_{a,b+1}-dp_{a,b}) = 1+b(dp_{a,b} - dp_{a, b - 1})+a(dp_{a - 1, b+1} - dp_{a - 1, b})\)

特别地,当 \(b = 0\) 时,有 \((a+m+1)(dp_{a, 1} - dp_{a, 0}) = 1+a(dp_{a - 1, 1} - dp_{a - 1, 0})\)

猜测 \(dp_{a, b} - dp_{a, b - 1}\) 是一个常数 \(\dfrac{1}{m+1}\),因为当 \(a = 0\) 时成立,代入 \(a = 1, b = 0\) 时也成立,然后即可数学归纳法证明(当然,你可以打表

再代入 \(dp_{a, b} - dp_{a, b - 1} = \dfrac{1}{m+1}\) 可得 \(dp_{a, b} - dp_{a-1, b + 1}= \dfrac{m(n+m+1)}{a(m+1)}\)

因此 \(dp_{n, 0} = \sum\limits_{a = 1}^n\dfrac{m(n+m+1)}{a(m+1)}+dp_{0, n } = \dfrac{(n+m+1)(1+mH_n)}{m+1}\),其中 \(H_n\) 是调和级数。

当然,还可以利用期望的线性性同样得到上面的柿子。

[NOI2020] 制作菜品

首先,当 \(m \geq n - 1\) 必然有解。一个简单的构造为取出最大值 \(mx\) 和最小值 \(mn\),若 \(mn \geq k\) 则说明 \(m \geq n\),此时直接用 \(mn\) 制作;否则必然有 \(mn+mx \geq k\)(等号只在 \(m = 1, n = 2\) 时取到 ),用反证法可简单证明,因此用一个最大和最小得到 \((m - 1, n - 1))\) 的子问题。随便输出一下方案就行了。

\(m = n - 2\) 时,猜测若 \(d_i\) 能分成两个 \(m = n - 1\) 集合时一定有解,充分性显然。必要性只用当 \(m = 1, n = 3\) 显然无解即可证明,于是直接将 \(d_i - k\) 做 01 背包即可,用 bitset 优化,时间复杂度 \(O(\dfrac{n^2k}{w})\),但是跑的很快。

CF566C Logistical Questions

只考虑一条边的两个端点 \(u, v\),设其最优带权重心距离 \(u\)\(x\),则代价为 \(a_ux^{1.5}+a_v(l - x)^{1.5}\),求导为 \(1.5a_u\sqrt x-1.5a_v\sqrt{l - x}\) 为凸函数,当导数小于 0 时将 \(x\) 增大,否则减小即可。

拓展到多个点也是相同的,由于凸函数之和仍然是凸函数,重心唯一。设当前在 \(u\)\(u\)\(i\) 的距离为 \(d_i\),则从 \(u\) 走到 \(v\) 的代价为 \(f(v) = \sum_{i \in sub_v}a_i(d_i - x)^{1.5}+\sum_{i\neq sub_v}a_i(d_i+x)^{1.5}\),求导为 \(f'(v) = 1.5\sum\limits_{i \neq sub_v}a_i\sqrt{d_i+x} - 1.5\sum\limits_{i\neq sub_v}a_i\sqrt{d_i - x}\) ,只用代入 \(x = 0\) 观察 \(f'(v)\) 是否 \(< 0\) 就进入 \(v\)

用点分治来逐步逼近,每次只用暴力算出 \(f(v)\) 和总答案,由于总计算次数为 \(O(\log n)\) 级别,因此时间复杂度 \(O(n\log n)\)

CF698F Coprime Permutation

有点怪,明天再补。

[JSOI2019]神经网络

最终哈密顿回路的形态是从 1 号树开始出发,每次在一棵树上走一条链切换到另一棵树上,最后把所有树覆盖完。

单独考虑每一棵树,其实就是把它分成若干条链的方案,每个长度 \(>1\) 的链方案数为 2,设 \(dp_{i, j, 0 / 1 / 2}\) 表示 \(i\) 子树内有 \(j\) 条链,且 \(i\) 的度数为 \(0 / 1/ 2\) 的方案。为了方便处理 \(l = 1\) 的情况,初始化 \(dp_{i, 0, 0} = 1, dp_{i, 1, 2} = \dfrac 1 2\),最后划分成 \(i\) 条链的方案就是 \((dp_{1, i, 1}+dp_{1, i, 2})\times 2^i\)。dp 转移只用考虑 \((u, v)\) 这条边加不加然后做背包。

然后考虑把几棵树的路径拼起来,但是必须要求相邻两条路径不能来自同一棵子树,否则会算重。直接容斥,将一棵树 \(i\) 条链合并成 \(j\) 条,容斥系数为 \((-1)^{i - j}\),方案为将 \(i\) 个有标号小球放进 \(j\) 个无标号盒子的方案,为 \(\dbinom{i - 1}{j - 1}\times \dfrac{i!}{j!}\)。最后把每棵树的答案卷起来就是总的选 \(i\) 条链的方案。最后每个长度 \(i\) 乘上圆排列方案 \((i - 1)!\) 相加。

[省选联考 2020 A 卷] 魔法商店

对每个 \(a_i\) 考虑 \(a_i\) 能被哪些数替代建出偏序关系。先在线性基中加入除了 \(a_i\) 的所有在 \(A\) 集合中的元素,然后依次判断 \(c_i\) 是否能再次插入,如果能则连边。对于 \(b_i\) 同理。

然后套 \(L_2\) 问题保序回归板子。流程是先整体二分,计算 \(f_i \in [l, r] /(mid, mid+\epsilon )\) 的答案,每个点只会取到 \(mid\) 或者 \(mid+e\),求导后算最小权闭合子图,再分治即可。

由于要求 \(f_i\) 为整数,当 \(r - l = 1\) 时就可以直接算 \(f_i = l\)\(r\) 的答案。

时间复杂度大概为 \(O(\log \max v_i \times \mathrm{maxflow}(n, nm))\)

2023.1.13

[NOI2019] 机器人

简单 DP:设 \(dp_{l, r, k}\) 表示区间 \([l, r]\) 最大值不超过 \(k\) 的合法放置的方案数,转移只需要枚举最靠右的最大值,则该位置放机器人能走完整个序列,且任何其他位置不能到达,\(dp_{l, r, k} = dp_{l, r, k - 1}+\sum\limits_{A_p \leq i \leq B_p}dp_{l, p - 1, k} \times dp_{p+1, r, k - 1}\) 。由于要求绝对值差 \(\leq 2\),因此合法的位置是 \(O(1)\) 级别。 时间复杂度 \(O(n^2k)\)

由于合法区间必然不多(打表可发现当 \(n = 300\) 时只有 \(2400\) 个不到),采取记忆化搜索,复杂度 \(O(2400k)\)

当所有 \(A_p = 1, B_p = 10^9\) 时,所有的转移都是一样的,且 \(dp_{l, l}\) 是关于 \(k\) 的一次函数,$dp_{l, l+1} $ 可以由 \(dp_{l, l},dp_{l+1, l+1}\) 得到,因此是一个二次函数。不难归纳,\(dp_{l, r}\) 是关于 \(k\)\(r - l+1\) 次多项式,因此只需要把前 \(n+1\) 个 dp 值算出来,然 后线性插值即可。

\(A_p\)\(B_p\) 不同时,先将区间左闭右开离散化,则算 \([l, r)\) 区间的 \(dp_{1, n}\) 时只需要得知 \(dp_{L, R, l - 1}\) 的 dp 值,如果我们从小到大处理区间的话,这是个常数。剩下的和 \([l, r)\) 在一段区间仍然可以插值。算完后再把当前的 \(r - 1\) 处的 dp 值插出来,赋值到下一轮的 \(dp_{l, r, 0}\)

[ZJOI2019]线段树

考虑一次修改 \([l,r]\) 会对线段树上的节点标记的影响,可将线段树节点分为以下 5 大类(图源来自 Sooke,侵删歉):

luogu.com.cn)

\(f_{u,i}\) 表示经过 \(i\) 次分裂后,线段树 \(u\) 号节点的标记个数。

  • 对于一类点,标记清空,\(f_{u,i - 1}\)
  • 二类点,一定有标记,\(f_{u,i- 1}+2^{i - 1}\)
  • 三类点,当且仅当 \(u\) 到根上的任意一点有标记时,它会得到标记,因此设 \(g_u\) 表示 \(u\) 到根都没有标记的方案,\(f_{u, i - 1}+2^{i - 1} - g_u\)。一类点:\(g_u \leftarrow g_u+2^{i - 1}\),二类点:\(g_u\)
  • 四类点:不改变当前状态,因此 \(f_{u, i - 1} \times 2, g_{u}\)
  • 五类点:都不改变,\(f_{u, i - 1} \times 2, g_u \times 2\)

遍历能遍历到 1,2,3 类节点,直接暴力更新即可。对于 4,5 类节点,都是乘法操作,因此线段树维护 2 两个乘法 tag 和当前 f, g 和 \(f_u\) 总和。

CF506E Mr. Kitayuta's Gift

由于统计不同的串的方案,于是直接从答案回文串的形态入手。答案串从左右往中间每次添加两个相同字符(\(|s|+n\) 为奇数且最后一次填除外)得到,而给定串 \(s\) 若是它的子序列则可以统计进答案。根据上面的过程,假设 \(|s|+n\) 为偶数,不难设计出一个区间匹配的 dp:

\(dp_{l, r, k}\) 表示已经往左右加入 \(k\) 对字符,\(s\) 与这 \(k\) 对字符尽量匹配后还有 \([l, r]\) 为匹配的方案(匹配必然是从左右往中间的)。

  • \(l > r\) 表明匹配完毕,因此随便加即可, \(dp_{l, r, k+1}\leftarrow d_{l, r, k} \times 26\)
  • \(l \leq r\)\(s[l] = s[r]\),有 \(25\) 种方案不能匹配,\(1\) 种方案匹配,\(dp_{l, r, k+1} \leftarrow dp_{l, r, k}\times 25\)\(dp_{l +1, r - 1, k+1}\leftarrow dp_{l, r, k}\)
  • \(l \leq r, s[l] \neq s[r]\),有 \(24\) 种方案左右都不匹配,一种方案匹配 \(l\),一种匹配 \(r\)\(dp_{l, r, k+1} \leftarrow dp_{l, r, k}\times 24,dp_{l+1,r,k} \leftarrow dp_{l, r, k}, dp_{l,r -1, k+1}\leftarrow dp_{l, r, k}\)

\(|s| = m\)\(k = \dfrac{m+n}{2}\)直接算 $ O(nm^2)$。强行将 \([l, r]\) 看成二维向量矩乘 $O(m^6 \log n) $,显然太劣。

\([l, r]\) 看做一个状态,状态的转移看做 DAG 上的连边,发现很多转移都是在走自环,设自环方案为 24 的为 24 点,25 的为 25 点,建出如下 DAG:

 (luogu.com.cn)

若一个从起点到终点的路径上有 \(a\) 个 24 点,则必有 \(b= \left\lceil\dfrac {m - a}2\right\rceil\) 个 25 点。对于具有相同 24,25 点的路径,其在转移之间插入自环的方案数相同(可以看做 \(a +b\) 个非负变量和为 \(k\) 的方案,变量之间显然是没有区别的)。只需计算出 \(a\) 个 24 点的方案和在 \(a\) 个 24 点,\(b\) 个 25 点中插入自环的方案相乘即可。

计算 \(a\) 个 24 点的方案:直接设 \(dp_{l, r, k}\) 表示当前在状态 \([l, r]\),已经经过 \(k\) 个 24 点的路径条数,记忆化搜索即可。时间复杂度 \(O(m^3)\)

计算 \(a\) 个 24 点,\(b\) 个 25 点的方案:可建立新的一张 DAG 连成一条链,\(s\) 向第一个 24 点连边,第 \(i(i < a)\) 个 24 点向 \(i+1\) 个 24 点连边,第 \(a\) 个 24 点向第一个 \(25\) 点连边,然后跑矩快。本质不同的 \(a\)\(O(m)\) 个,时间复杂度 \(O(m^4\log n)\)。 不优秀。

问题在于我们没有利用矩快可以求出任意两点之间的长度为 \(k\) 的路径条数,考虑直接把这 \(O(m)\) 个路径整合到一起,如下图:

(luogu.com.cn)

红点为 \(m - 1\) 个 24 点,绿点为 \(\left\lceil\dfrac m 2\right\rceil\) 个 25 点,每个 25 点连向终点 “26” 点。这样的话算整个的矩快,若要计算有 \(a\) 个 24 点的方案,只需要提取倒数第 \(a\) 个红点到第 \(\left\lceil\dfrac{m - a} 2\right\rceil\) 个绿点之间的路径条数即可,时间复杂度 \(O(m^3\log n)\)

还有一个问题:当 \(n+m\) 为偶数时,最后一次只能添加一个字符,只需要钦定最后一次选择的是 24 点,然后再容斥一下即可。

2023.1.14

P4727 [HNOI2009]图的同构计数

考虑 Burside 引理:\(|X(G)| = \dfrac{1}{|G|}\sum\limits_{g \in G}|X^g|\)。将每条边看做有 \(0\) 或 1 的颜色,则 \(|X| = 2^{\frac {n(n - 1)}2}\)\(|G|\) 为全体置换 \(n!\)

先考虑置换的所有轮换,设其大小为 \(k\)

考虑两个端点都在其内部的方案,问题相当于一个 \(k\) 个点的完全图的等价类个数,每个长度为 \(i(i \leq \dfrac k 2)\) 的边都会形成一个等价类,因此贡献为 \(2^{\frac k 2}\)

考虑一条边的端点不在同一个轮换的情况,设两个轮换的大小为 \(s1, s2\),此时随着两个轮换的进行,会在 \(\mathrm{lcm}(s_1,s_2)\) 后回到原点,因此会有 \(\dfrac{s1 \times s2}{\mathrm{lcm}(s_1,s_2)} = \gcd(s_1, s_2)\) 个等价类,每个等价类的贡献同样为 \(2^{cnt}\)

因此,对于一个置换 \(P\),设其分解成所有轮换的大小为 \(s_1,s_2,\dots, s_k\),贡献为 \(2^{\sum\limits_{i = 1}^{k}\left\lfloor\frac {s_i}2\right\rfloor+\sum\limits_{i, j, i<j}\gcd(s_i, s_j)}\)

直接 \(O(n!)\) 枚举置换显然不现实,注意到我们只关心轮换的大小,因此可以拆分数枚举,根据经典结论,\(p(n) \sim \dfrac{1}{4n\sqrt3 }\exp(\pi\sqrt{\dfrac{2n}3})\)

每个拆分方案 \(s_i\) 的方案为 $\dfrac{1}{n!} \times \dfrac{n}{\prod\limits_{i = 1}^{k}s_i!\sum\limits_{i = 1}^{p}cnt_i!}\times \prod\limits_{i = 1}^{k}(s_i - 1)! = \dfrac{1}{\prod\limits_{i = 1}^{n}cnt_i!\times \prod\limits_{i = 1}^ks_i} $,其中 \(cnt_i\) 表示长度为 \(i\) 的轮换个数,显然长度相同的轮换是没有区别的。

时间复杂度 \(O(p(n) \times poly(n))\)

[清华集训2017]生成树计数

若有 \(n\) 个连通块,每个大小为 \(a_i\),每个连通块度数为 \(d_i\) 连成一棵树的方案为:\(\prod\limits_{i = 1}^{n}a_i^{d_i}\times\dfrac{(n - 2)!}{\prod\limits_{i = 1}^{n}(d_i - 1)!}\), 枚举每个点的度数

\[\mathrm{val} = \sum\limits_{d_i= n - 2} \prod\limits_{i = 1}^na_i^{d_i} \times \dfrac{(n - 2)!}{\prod\limits_{i = 1}^{n}(d_i - 1)! }(\prod\limits_{i = 1}^nd_i^m)(\sum\limits_{i = 1}^nd_i^m) \\ =(n-2)!\sum\limits_{d_i = n - 2}(\sum\limits_{i = 1}^n d_i^{2m}a_i^{d_i}\dfrac 1{(d_i- 1)!} \times \prod\limits_{j \neq i}d_j^ma_j^{d_j}\dfrac{1}{(d_j - 1)!}) \\ \]

注意到前后两个形式类似,考虑设 \(A(x) = \sum\limits_{k \geq 1}\dfrac{k^{2m}}{(k - 1)!}x^k\)\(B(x)= \sum\limits_{k \geq 1}\dfrac{k^m}{(k - 1)!}x^k\),则 \(= [x^{n - 2}] \sum\limits_{i = 1}^{n}A(a_ix)\prod\limits_{j \neq i}B(a_jx) = (\sum\limits_{i = 1}^{n}A(a_ix)) \times (\prod\limits_{i = 1}^{n}\dfrac{A(a_ix)}{B(a_ix)}))\)

考虑前面一部分,\(\sum A(a_ix)\)\(k\) 次项系数为 \(A[k] \times (\sum\limits_{i = 1}^{n}a_i^k)\),可以预处理每个 \(k\) 次幂 \(c_k = \sum\limits_{i= 1}^{n}a_i^k\) 计算。

考虑后面一部分,经典 Ln + Exp:\(=\exp(\sum\limits_{i = 1}^{n}\ln(\dfrac{A(a_ix)}{B(a_ix)})\)。同样可以利用 \(c_k\) 计算,但 \([x^n]F^k(x) = [x^{-k}]\dfrac 1 n G^{-n}(x)\)

鸽子的老家

谨防新型信息诈骗,主要特征有:

  • 含义不明的数字,例如 \(1.242803739^{(m - 1)(m - 2)}\)
  • 表述奇怪的函数,如 \(\sum\limits_{1 \leq a_1 <a_2<\dots <a_m \leq n}[\prod\limits_{1 \leq i < j \leq m}|P(a_i, a_j)\cap S|]\)
  • 非常的模数,如 \(1914270647\)

随便找一个 \(a_i\) 作为根,显然有 \((m- 1)\) 条路径至少有 1 的权值,考虑路径两两配对,至少有 \(\dfrac{(m-1)(m-2)}2\) 个 2,由于 \(\sqrt 2 > 1.2428\dots\),问题就是找 \(m\) 个点,使得任意两对点之间有一条关键边。

时光倒流,考虑非关键边形成的连通块,显然每个连通块最多选一个点,方案为 \(a_i\),答案即是选择 \(m\) 个点的总方案,背包即可,每次合并两个连通块只用撤销两个背包,加入一个背包。

时间复杂度 \(O(nm)\)

鸽子做加法

首先整数和小数可以分开考虑,每个分数向下取整后都可以写成一个整数 + 正真分数。利用 \(a \ \mathrm{xor} \ b = a+b - 2 (a \ \mathrm{and} \ b)\),于是可以只用算与。前面的非循环节部分不好处理,可以把分母不断 \(/2\) 变成奇数,此时两个都必然是纯循环小数。

考虑如何求纯循环小数的循环节,这是个经典问题

看做二进制除法,若分母 \(<\) 分子则商 0,否则商 1,分子减去分母,每次将余数 \(\times 2\) 就是答案。循环节即是分子第二次为 \(p\) 的位置 \(-1\)。 显然 \(\dfrac p q\) 的循环节长度不会超过 \(q\)。设两个分数的循环节长度分别为 \(l_1, l_2\)

显然答案的循环节长度不超过 \(m = \mathrm{lcm}(l_1,l_2)\),同时也是一个纯循环小数,因此只用算出在前 \(m\) 位的表示,再利用等比数列 \(a+a2^{-m}+a2^{-2m} = \dfrac{a}{1 - 2^{-m}}\) 计算。

显然 \(ans_i = a_{i \bmod l_1} b_{i \bmod m_2}\) ,直接计算就是 \(O(m)\) 的,考虑利用同余的性质优化:对于任意一个 \(i\)\(j\)\(a_i\)\(b_j\) 同时出现的位置 \(x\) 满足:

\[\begin{cases} x \equiv i \ (\bmod l_1) \\ x \equiv j \ (\bmod l_2) \end{cases} \]

直接用扩展 CRT 解 \(x\) 显然没有前途,考虑 \(l_1 \perp l_2\) 时,直接用普通 CRT,则$ x = i \times l_2 \times l_2^{-1} + j \times l_1 \times l_1^{-1}$,其中 \(l_2^{-1}\)\(\bmod l_1\) 意义下 \(l_2\) 逆元注意到贡献为 \(2^{-x} = 2^{-i\times l_2 \times l_2^{-1}} \times 2^{-j \times l_1 \times l_1^{-1}} \times 2^{m[i+j \geq m]}\) 关于 \(i, j\) 两维几乎是独立的,只需要在 \(i + j \geq m\) 时加上 \(2^{m}\) 的贡献,可以排序后分别计算 和 \(<m\) 的和 \(\geq m\) 的。这样就可以 \(O(n\log n)\) 计算。

当然 \(l_1,l_2\) 不一定互质,此时任选两个下标 \(i, j\) 不一定能对应,但注意到条件为 \(\gcd(l_1,l_2) \mid i - j\) ,因此可以按照模 \(d = \gcd(l_1, l_2)\) 余数进行分组,在相同组的可以按照上面的计算,在不同组的,显然不能两两对应。在同一组的满足互质的性质。

CF434E

正难则反,设两点之间边权为 1 表示 \(G(S(s, e)) \equiv x(\bmod y)\),否则为 0。计算非法三元组数量,设 \(x \to y \to z, x \to z\),规定 \(x \to z\) 的颜色后,\(x \to y \to z\) 有三种情况。但直接统计三元数量不好统计。

观察非法三元组形态,必然存在一个点,和它有关系的边分别为 0 / 1,在一个坏三元组中会恰好有两个这样的点,因此算出这样的点个数 \(/ 2\) 即可。

若钦定 \(x\),则满足 \(y \to x\) 为 0,\(z \to x\) 为 1;或 \(y \to x\) 为 1,\(z \to x\) 为零,简单的讨论后,设 \(in_{0, 1}\) 表示 0 / 1 入边个数,\(out_{0, 1} 同理\),对于一个点,方案总和为:

\(in_0 \times in_1 \times 2+out_0 \times out_1 \times 2+in_0 \times out_1 +in_1 \times out_0\)

\(in_{0, 1}, out_{0, 1}\) 的计算点分即可。由于 \(y\) 是质数,路径满足可减,容易开桶统计。

CF375C

trick:判断一个点是否在多边形内部可以引一条该点为端点的射线,若射线与多边形奇数个交点则在内部。

因此,设 \(dp_{x, y,S}\) 表示当前在 \((x, y)\),只考虑当前多边形的边 \(S\) 中的点在内部。我们可以钦定所有射线都是平行于 \(x\) 轴的就可以得到新的状态。

注意边界上的点不能计算入答案,一种处理方法是强制边界点不能选 B 和 数字,且横着的线段可以忽略,对于竖着的线段,钦定左闭右开即可。

用 BFS 转移即可。

CF1336F

将两条路径的交分成两部分,一种 LCA 相同,一种不同。

设当前链分别为 \(A,B\),端点为 \(s_A, t_A, s_B, t_B\),设 \(l_A = \mathrm{LCA}(s_A, t_A), l_b = \mathrm{LCA}(s_B, t_B)\)\(dfn_{s_A} < dfn_{t_A}, dfn_{s_B}< dfn_{t_B}\)

  • \(l_A \neq l_B\)

    https://codeforces.ml/predownloaded/95/e5/95e531fd6d6710c30f67f54a3a70332bfdde45a0.png

    假设 \(l_A\)\(l_B\) 祖先,从根自顶向下进行 DFS,在更深的 LCA 处统计答案,在 \(E,F\) 处单点加,在 \(B\) 处统计答案,找到 \(B\)\(G, H\) 分别走 \(k\) 步到达的点,进行一次子树求和。

  • \(l_A = l_B\)
    https://codeforces.ml/predownloaded/fc/a0/fca00e8fdae5ddc2e82355dea768994e4315cc50.png

    枚举 \(l_A = X\)

    由于保证了 dfn 序的大小关系,固定 $s_A $ ,则 \(t_A\) 的相对顺序有三种:2,3,4。其中 34 是本质相同的,因为都是同一子树的不同点匹配。

    \(t_A\) 挂在 \(s_A\) 上,枚举 \(E\) 的两个子树进行启发式合并。设 \(E\)\(t_A\) 方向走 \(k\) 步到达 \(H\) (若走过 \(t_A\) 显然非法,不足 \(X\) 则直接到达 \(X\)),询问在起点另一颗子树内的,且终点在 \(H\) 子树的点对,显然可以启发式合并 + 线段树合并。

    对于 \(t_A\) 相对顺序为 2 的情况,此时两个路径只有一端有相交。

    https://i.loli.net/2020/04/17/fMFSq7ialm8RDC5.png

    将所有链按照起点的 dfs 序排序,枚举到 \(s_A, t_A\) 时,在 \(t_A\) 单点加;枚举到 \(s_B, t_B\) 时,从 \(X\)\(k\) 步到 \(D\),查询 \(B\) 的子树和。

时间复杂度 \(O(n\log^2 n)\)

总结:

  • 根据题目的提示也许有助于分讨。
  • 加强条件,从而减少可能的方案,取而代之的是繁琐的分讨。
  • 线段树合并 + 启发式合并可以暴力地解决问题。

posted @ 2022-09-30 17:11  henrici3106  阅读(120)  评论(0编辑  收藏  举报