杂题选写1
P3714 [BJOI2017] 树的难题
搞笑吧。单点取 mx 写成单点推平,调了半个小时。。
首先数路径的题可以用点分治做到数路径 O(nlogn)O(nlogn),接下来是怎么统计答案。
注意到答案分为三类:两端同色,两端异色,只取一端。其中第三种可以和一条颜色为 0,长度和权值和为 0 的路径匹配,转为情况二。
考虑按颜色枚举,再在同一颜色内枚举子树,然后枚举每条链。可以开两颗线段树分别是同色的链信息和异色的链信息,同长度的链贪心取权值和最大的,然后就线段树了,其中每个颜色枚举完之后要将同色的这棵合并到全局异色,然后新开一棵同色的。
P10220 [省选联考 2024] 迷宫守卫
有一个基本的思路是贪心选第一个最小然后递归。
具体地,二分第一个数,然后 dp 判断花费是否合法,有 dpu=min(dpls+au,dpls+dprs)。
然后判断往哪边走。
如果是往右边走,那么当前点不会被选,按题意递归。
如果是往左边走,先往左边走,此时需要判断该点是否会被选,注意到不是 wu⩽dprs 就选,因为有的时候可以不选的。
被选当且仅当不选时左子树答案会发生变化,也就是左子树费用+右子树预期费用超过了总费用。
复杂度 O(2nn2)。
P7517 [省选联考 2021 B 卷] 数对
狄利克雷前缀和,做完了。
P10218 [省选联考 2024] 魔法手杖
先建 trie 树,节点记录挂在这个节点上的数集的 min_a 和 sum_b,然后考虑解决问题。
首先对于全局 ∑b⩽m 显然答案是 mina+2k−1,特判。剩下的情况答案都不会超过 2k−1,因此考虑逐位确定答案。
从上往下遍历节点。对于一个节点,在 dfs 时记录当前确定的 x,当前得到的答案 ans,当前的位 j,还有的费用 k,当且最小的 mna 需要满足 mna+x⩾ans。
首先,若当前子树为空,那么剩下的贪心取最大,也即 mna+2j+1−1。
否则,分类讨论当前位取什么。
- 如果取 1,则必定一棵子树为异或,一棵子树为加。以左子树为加为例,那么 x 这一位取 0,同时需要满足一定条件。首先需要费用足够,其次要有最好情况下能成立也就是 min(mna,mnals)+(x+2j−1)⩾(ans+2j)。如果成立了,更新信息,向下递归。右子树是类似的
- 如果取不了 1,就只能取 0。观察 x 这一位取什么,以取 0 为例,则右子树的异或值都比左子树大,递归左子树即可。取 1 类似。
这样就好了。
P7514 [省选联考 2021 A/B 卷] 卡牌游戏
比较妙的神金卡常题。
先二分答案,再枚举值域区间,容易发现一定是中间一段不用翻。那么判断翻的是否合法就好了。O(nlogn+nlogV),卡常被卡死了。
P7521 [省选联考 2021 B 卷] 取模
双指针 O(n2) 直接过了,震惊。
哦根据 I_am_Accepted 的题解证明,原来我的做法是 O(nlogn) 的。
P7520 [省选联考 2021 A 卷] 支配
建支配树。首先,如果一个点会发生变化,那么它的受支配集也会变,也就是支配树上的子树。
判断树上最上面一个点是否会变,也即有路径 1→x→y→u 不经过 fau,那么可以预处理连通性做到 O(n2+nq),轻微卡常。
P7516 [省选联考 2021 A/B 卷] 图函数
观察怎么样的 v 可以给 f(u,G) 做贡献。观察得到存在 u→v,v→u 两条路径,走过的点均满足在 [v,n] 内。
考虑反证,比如有一个最大的点 x(x<v) 会被经过,那么 x 与 u 单向连同,因为如果双向连同就被删了,不连通就是个废物。
不妨设 x→u,那么存在 v→x→u 和另一条 u→v 的路径,发现有了 u→v→x,矛盾,故不存在,其他情况类似。
倒序加边,记录每条边的加入的时间戳,由于做贡献的点对不会因为加边而不做贡献,可以路径上取 min,路径间取 max 来贪心找到最后一个做贡献的图。
又由于有值域限制,倒序枚举中转点做 Floyd 就好了。
P6627 [省选联考 2020 B 卷] 幸运数字
好纯正的签到题。
答案就在给的端点附近,离散化以后线段树区间静态异或。
P6626 [省选联考 2020 B 卷] 消息传递
点分治。深为 k 的节点数就是长为 k 的简单路径数。
处理分治中心时计算所有询问过该点的路径数。用桶就好了。
P6628 [省选联考 2020 B 卷] 丁香之路
好厉害啊。
观察到对于给定的 t 求的是一条欧拉路径。那么连上 t→s 就变成欧拉回路。根据其充要条件可以较快速的算出。
首先,每个点的度为偶。那么我们可以先把所有必须走的边拿出来,拎出奇度点,容易发现有偶数个。按编号排序,走 2k−1 与 2k 之间的边,容易发现这样的代价是最小的。
然后,图连通。首先找出所有连通块。由于走只能走 ±1 的道路,拿出来对连通块跑 MST 即可,复杂度 O(n2logn)。
P6619 [省选联考 2020 A/B 卷] 冰火战士
发现排序是没用的。观察到答案肯定是某个人的战力,那相当于先离散化,开两个桶,要单点修改,答案就是
发现这两个前缀和 f 和后缀和 g 的函数形式满足单增和单减。容易发现最值应该在交点附近。
只要找到交点,那么就可以直接旁边看看就好了。
由于是离散函数,可以连续一段值不变,因此虽然是凸函数但不能三分。
但是 hi=[fi<gi] 是一个前 1 后 0 的函数,并且分界点与交点相近,因此可以找这个分界点。
朴素的做法是二分加树状数组查询,复杂度 O(mlog2n),过不了。
考虑人类智慧般逼近,观察树状数组的定义,发现如果类似倍增的做法,从高到低枚举分界点下标的每一位二进制位是否为 1,可以 O(1) 得出这个点的 h 值。
那么复杂度就变成 O(mlogn),离散化别用 map 就能过。
P6623 [省选联考 2020 A 卷] 树
首先可以拆位。观察哪些节点 u 会在祖先 f 处做贡献。
观察 u+i 的第 j 位,发现其有一个 2j+1 的循环节,前 2j 为 0 后 2j 为 1,因此会在距离 u 满足距离在 [n2j+1+a,n2j+1+2j+a) 的范围内,其中 a 是容易计算的,也就是某个循环节中第一个 1 出现的位置。
发现区间问题不好做,差分成单点修改,最后求子树和。发现操作相当于对所有为 u 祖先、深度为 p2j+au+depu 的点进行单点修改。那么我们只要遍历树时维护一个大小为 2j 的桶,单点修改就是修改桶中 au+depu 的位置。计算 u 的答案时,就是观察它的子树节点们对 depu 位置的贡献,可以时间上差分,也就是访问前和访问后对应位置的值的差分值。
那么就做完了,复杂度 O(nlogV)。
P5323 [BJOI2019] 光线
观察到相邻的两个玻璃貌似是可以合并的。我们记录从某侧到某侧的光的通过率的信息,那么就可以一路合并到只剩一个玻璃。
那么怎么合并呢,考虑用矩阵 a[0/1][0/1] 存储信息,表示玻璃 a 的上/下侧单位 1 光射入,从上/下侧射出光的量。
使用暴力推柿子就可以解决,柿子可爱就不放了。
P5319 [BJOI2019] 奥术神杖
极品题。
观察答案 ans=|S|√∏wsi,这啥啊。
指数不好搞,取个对数变 lnans=1|S|∑lnwsi,最大化 lnans。
然后变成 01 规划,二分 lnans 的值 x,判断右边减左边是否大于 0。化简可得 ∑(lnwsi−x)>0。
那么对于串们建立 ACAM,然后每次二分就暴力算每个点的权值(注意全树前缀和),dp 计算即可,要记录转移点。
复杂度 O(|T|∑|S|loglnV)。
点边容斥 / 点减边容斥
- 对树上点染色,那么对于某颜色,连通块数 = 该色点数 - 两端都是该色边数。
- 对于树上统计方案,若任意方案中点一定构成仅一个连通块,则方案数 = 钦定经过某点的方案数 - 钦定经过某边的方案数。
两种本质是相同的,都是容斥,所以可以通过观察每种方案的贡献是否正确来证明其正确性。
P10064 [SNOI2024] 公交线路
最紧的限制显然在叶子。设点 u 仅走一次所能到的点集为 Su,则对于任意 u,v 要求 Su∩Sv≠∅。
等价于对于叶子集合 V 满足 ∪u∈VSu≠∅。
观察到 ∪u∈VSu 是一个连通块,因此可以使用点边容斥计算方案数。
考虑如何计算经过点 u 的方案数,发现充要条件是一步可以走到所有叶子,发现不好处理,再考虑二项式容斥一下。
设全局以 u 为根。令 fv,i 表示子树 v 内钦定了 i 个叶子不与 v 连通的方案数。那么要求的就是 leafu∑i=0(−1)ifu,i。
考虑使用树形背包的样子递推,令孩子 v 合并到 u 上了,那么 f′u,k=∑i+j=kfu,i(leafvj)2szv(szv−1)22(szu−i)(szv−j)。
这样复杂度是 O(n3) 的,过不了。
注意到树形背包卷积复杂度是 O(n2) 的,考虑用这种方式优化。
以一个非叶子节点为根,n=2 特判。
算到 u 时,只算它当前的子树。它的还有一棵没算的是外面的子树(令其大小为 szo,叶子数为 leafo),此时可以不需要容斥计算,因为可以保证全部连通,方案数为 leafu∑i=0(−1)ifu,i2szo(szo−1)22(szo−leafo)(szu−i)(2szu−i−1)leafo。
计算边也是类似的。令较深的点为 u,也是对于 u 子树容斥,u 外面不容斥,方案数为 leafu∑i=0(−1)i(leafui)2szu(szu−1)22szo(szo−1)22(szo−leafo)(szu−i)(2szu−i−1)leafo.
复杂度 O(n2)。
积累一个 trick:树形背包复杂度为 O(n2)。
证明:对于每一个点对,仅会在其 lca 处被枚举到并计入贡献,因此复杂度是 O(n2)。
slope trick
一种优化 dp 的手段。
比如对于 CF713C,有转移式 fi,j=mink⩽jfi−1,k+|ai−j|。
改写成函数,令 Fi(j)=fi,j,Gi(j)=mink⩽jfi,k,则转移可写成 Fi(j)=Gi−1(j)+|ai−j|。
观察到 G 是下凸函数,绝对值函数是下凸函数,所以 F 也是下凸函数。
因此可以使用 slope trick 优化。
具体地,记录分段函数的分段点们。由于本题不需要维护斜率大于 0 的部分,因此只维护小于等于 0 的部分。每一次的答案就是 0 的分段点。
分类讨论维护,考虑 Gi−1→Gi 的变化,令当前分段点可重集合为 S,0 端点为 x,当加入 |ai−j| 时:
- 若 ai⩾x,对于 <ai 的部分整体斜率加 1,对于 ⩾ai 的部分取完 min 后斜率还是 0,因此只需要加入 {ai}。
- 若 ai<x,对于 <x 的部分整体斜率加 1,对于 ⩾x 的部分取完 min 后斜率还是 0,因此需要加入 {ai,ai} 并删除 x。
复杂度是 O(nlogn) 的,维护方法是可以通用的。
AT_agc049_e [AGC049E] Increment Decrement
发现没有什么贪心策略来求序列确定时的最小花费,那就 dp。
容易发现,如果先进行了几次区间操作变成了 b,那么总花费为 n∑i=1|ai−bi|+mmax(bi−bi−1,0)。
因此,可以令 fi,j 表示考虑到了第 i 位,且 bi=j 的最小花费,易得转移式 fi,j=minkfi−1,k+|ai−j|+mmax(k−j,0)。
发现 fi,x 关于 x 是一个下凸函数,使用 slope trick 优化。观察函数形式,易得转移时加上的分段函数斜率在 [−1,m+1] 之间。
容易发现 fi 斜率也在 [−1,m+1] 之间。可以认为转移时如下(画图理解):先取 min,再加上 mmax(k−j,0),k=−1 的段变为 k=0,k=m+1 的段变为 k=m;再加上绝对值函数。
容易发现 f0 是一条斜率为 m 的过原点的直线,因此可以整个 dp 用 slope trick 维护。
具体地,每次删掉分段点中的最大值和最小值,再将两个 ai 丢入决策点。此时最小值 mn 即为 k=−1→k=0 的分段点(也是全局最优决策点之一),用它来贡献答案 ai−mn(也就是函数全局最小值的变大量,可以手模证明正确性)。
至此,已经可以求具体序列的答案了。
对于 Kn 个不同的序列,考虑拆贡献。对于贡献 ai−mn,其中 ai 系数是好算的,为 kn−1,关键在于 mn 的贡献。
也就是要求所有出现过的数 x,其出现在 mn 上的出现次数。
发现不好做,使用很牛的 trick:任意值转 01 值。
考虑如果我们能统计 ⩽x 的数次数 hx,那么可得 x 的出现次数为 hx+1−hx。
那怎么求 hx 呢?其实此时相当于只有两种数,0 代表所有 ⩽x 的数,1 代表所有 >x 的数。
那么维护只有 01 的分段点集合是容易的,某一步答案为 0 当且仅当分段点集合不全为 1。
令 fi,j 表示考虑到了第 i 位,分段点集合中有 j 个 0 的方案数。
首先可以处理出第 i 位可以填多少 0,设为 c。
根据前面的 slope trick 处理方式,j 在转移时要先扔掉最大值和最小值。然后根据选择放进去两个 0 还是 1 进行对应的转移。
由于分段点集合大小为 m+2,因此最后的方案数就是 n∑i=1m+1∑j=0kn−ifi,j。
至此,做完了。复杂度 O(n2mk)。
CF1416F Showing Off
牛逼。
首先整张图是一个内向基环树森林。对于每棵基环树,由于四连通,它的环长一定是偶数。发现如果一个环长度大于 2 那么可以拆成一个长为 2 的环和另一个环,答案仍合法,因此可以搞成所有环都是 2。
对于一个环,环上数字都相等。那么我们可以发现,如果一个数四周的数没有比它小的,若有答案,则它一定在环上;否则它可能在环上可能在链上。
使用黑白染色 + 网络流解决。对于黑点若它一定在环上,源点向它连 [1,1] 的边表示要匹配一个环,否则连 [0,1] 表示它可以匹配一个环;对于白点也是一样,只是是它连向汇点;对于黑白间点,黑点向它相邻的数相等的白点连 [0,1] 的边,表示可以匹配。(其实就是二分图匹配)
可行当且仅当存在可行流。同时黑白点间的边满流说明匹配成功,可以顺便构造出所有环的情况。
对于链,随机找一个相邻的比它小的连边即可。赋值是简单的,环上两个点一定可以选一个赋为 1,另一个作差,链上的也作差。
P5303 [GXOI/GZOI2019] 逼死强迫症
推一推可以 dp 得到 dpi=dpi−1+dpi−2+2i−3∑j=0fj,其中 dpi 为原问题方案数,fi 为不考虑 1×1 方案数,易得 f0=1,fi=fi−1+fi−2。
那么直接
复杂度 O(Tk3logN),其中 k=5。
P5290 [十二省联考 2019] 春节十二响
对于一个节点 u,如果我们已经知道目前 u 这棵子树以及子树 v 分别要多少,合并答案是容易的,就是从大到小排序之后依次去 max,在所有子树都算完后丢进去 u 自己需要的大小。
合并时考虑启发式合并,每次小的往大的上合并,复杂度是 O(nlogn) 的。
复杂度证明:一次取 max 等价于丢掉一个数的信息,丢的数是 O(n) 的,算上查询的复杂度,因此为 O(nlogn)。
P5321 [BJOI2019] 送别
容易发现对于每一个点它的后继是确定的。同时对于每一个坐标,由于可能有横着的墙和竖着的墙,相同的坐标可能代表不同的点(内外侧之分)因此要把一个坐标拆成四个点,左上右上左下右下各一个。那么这样每个点的后继就是唯一且确定的,且整张图是若干个环。
对于一次加墙或者删墙,其实就是更换两个点的后继。那么我们可以对于每个环开一棵 FHQ 维护(断环为链即可),并维护每个点到其后继的距离。这样就可以完成查询了。
注意到整张图环断了以后其实是森林,因此 LCT 也是可以维护的。
复杂度 O(nlogn),做完了,代码是真的长。
P4155 [SCOI2015] 国旗计划
发现有一些人是无用的,可以算出每一个人的后继点。钦定一个人必须被选可以把它当起点走,走到走了一圈就好了。走的过程倍增找就好了。
复杂度 O(nlogn)。
P5338 [TJOI2019] 甲苯先生的滚榜
【模板】平衡树
P5305 [GXOI/GZOI2019] 旧词
首先可以认为是依次激活每一个点。观察 k=1 时求的是什么。对于一个 lca 的深度之和,可以转化为 lca 到根之间的点的数量,那么每次就是求所有 lca 到根之间的点的数量。这不好求,但是注意到 lca 一定在根与 u 之间,因此可以转化为求根到 u 路径上每一个点的子树内被激活的点的个数,这个个数会在这个点出算为 lca。激活一个点就是修改一条链,查询就是查一条链,因此树剖就好了。
沿用这种做法,当 k≠1 时相当于是每种深度的权不一样了,那就算一算就好了,深度为 d 的权为 dk−(d−1)k,其他就和 k=1 一样了。
复杂度 O((n+q)log2n)。
P8339 [AHOI2022] 钥匙
厉害啊。好题。
发现每个颜色独立,考虑离线询问对每种颜色单独处理。
对于每种颜色,容易发现一个钥匙与一个宝箱配对,当且仅当钥匙到宝箱的这条路径是一条合法括号序列。由于钥匙数量少,可以枚举钥匙找宝箱。为了保证复杂度可以建虚树。
那么统计答案时就是算路径上有多少对我们枚举出来的钥匙-宝箱有序对,这个可以变成 dfn 序之后的二维数点,分类讨论一下即可。
复杂度 O(5nlogn+mlogn)。
P6793 [SNOI2020] 字符串
相当于两两匹配求 lcp 之和,要和最大。那么容易发现我们可以贪心的每次取一对使得其 lcp 为当前最长,正确性可以使用邻项交换。
求 lcp 长度可以考虑使用 SA 的 height 求,把两个字符串通过拼接符拼起来即可。
相当于根据 height 从大往小插入每个位置,每个插入的点在排名上与自己相邻的点构成连通块并记录连通块内未匹配的两种子串的数量。
那么插入时形成的匹配数是容易计算的,同时由于是从大往小插的,它们的 lcp 长就是 height 值。
复杂度 O(nlogn)。
P2178 [NOI2015] 品酒大会
与上题类似,求 lcp 转化为 height,然后 height 从大到小插入保证长度。
维护极长连续且已插入的子段 (l,r] 连通块,记录连通块大小和块内最大值最小值。答案是容易维护的。
P3203 [HNOI2010] 弹飞绵羊
相当于是在森林上跳,因此直接拿 LCT 维护即可。
P4324 [JSOI2016] 扭动的回文串
pkusc2024d1t1,可惜赛时最后一分钟才想到的。
分五种情况讨论:回文中心在 s 上,s 空,t 上,t 空,st 之间。
每种情况做法类似,就是二分找极长,找完后再换行,能找到最优解。
P6569 [NOI Online #3 提高组] 魔法值
首先是矩阵快速幂,这样就 O(qn3loga) 了。然后过不了。
注意到算 At 是 O(n3) 的,优化不了。那就算 vA2t1A2t2⋯ 好了,预处理 O(n3loga),询问 O(qn2loga),过了。
注意到乘法对异或没有分配率,不过没关系,因为对 01 有的,挂不了。
CF444C DZY Loves Colors
颜色段均摊,修改和询问分散到若干个颜色段内,每个段内修改,复杂度很对!
P5610 [Ynoi2013] 大学
注意到你可以直接暴力,高贵的颜色段均摊会告诉你复杂度的正确。
对于每一个数存下它的会修改的数的位置,然后修改的时候直接修改,对于 会修改的数的位置 的修改无须担心,可以懒惰处理。查询随便拿一个 BIT 即可。
然后是卡常。
首先分解因数复杂度是 O(na12),太慢了,使用高贵的筛子,就可以做到大概 O(na13) 以下。
然后是找会修改的数,set 太慢了,可以使用并查集连边直接跳,复杂度是 O(α(n)) 的,很高贵。
注意谨慎开 ll,快读要开 ll,快读要开全 ll。
CF453E Little Pony and Lord Tirek
牛啊。使用高贵的颜色段均摊,将同一次修改的段视为一个颜色。
在不考虑初始值的影响下,每次查询就是对于若干个段的查询的和,然后再染一次色,容易发现复杂度是对的。
注意到同一个段的颜色相同,那么可以二维数点 时间维 和 下标维 查询答案的函数表达式。然后就做完了。离线做比较简单,直接线段树即可。
在考虑初始值的影响下,容易发现对于每个点最多影响一个查询,暴力找出来算即可。
注意审题。
P4036 [JSOI2008] 火星人
别被骗了!动态字符串!
二分哈希就好了,维护哈希用一棵平衡树就好了!
n 很小嘛,询问又更小,所以是可以 O(mlog2n) 的。
P6617 查找 Search
类似于 HH 的项链,连一下前驱后继(以后继为例),然后转化为 rmini=lnxti⩽r 是否成立。维护就用线段树。
怎么求 nxt?注意到更改一个数只有常数个数的后继会变,把那些数找出来,就可以了。
为了保证复杂度,只在边界处连后继,中间部分全部指向 inf,容易发现是不劣的。
注意一定要把修改改完了再去改那些后继会变的的数的后继!
CF21D Traveling Graph
每条边至少经过一次?欧拉回路!
为什么要重复走?不完全欧拉回路。
注意到重复走等价于加边,加的权值一定是最短路,加的点一定是奇度点。
做完了。
CF702F T-Shirts
每个人独立,策略是先把商品排序,能买就买。这种暴力是平方的,考虑优化。
注意到买的过程是难以优化的,那我们可以让所有人一起买。那么就可以考虑平衡树维护存款,每次区间减就好了。
注意到如果这个商品价格为 c,那么 [0,c) 不变,[c,2c) 要变减小 c,是无法直接合并的,暴力插入。[2c,+∞) 直接打标记正常合并。
注意到对于 [c,2c) 来说,值至少减掉了一半,所以这样的操作数量是 O(nlogV) 的,可以过!复杂度应该是 O(nlognlogV)。
AT_arc107_f [ARC107F] Sum of Abs
很神奇啊!
注意到少有的正负权值,考虑类似最大权闭合子图做法,先把所有贡献全部加上再减去最小的需要去除的。
所有贡献即 ∑|bi|。那么对于不同的操作方式,要去除的分别是 0,2|bi|,ai+|bi|。
也即我们要将这些点分到正负两个集合里,考虑如何刻画。
注意到分两个集合可以考虑最小割的事情,考虑如何建图。
由于可以删点,需要拆点,入点和出点,之间连删掉的代价的边。那么如果不删,还要考虑所在集合的事情。
以 S 为正集合,bi<0 为例,那么分到 S 需要 2|bi| 的代价,为了保证这是在不删点的前提下的,可以 S 向入点连 2|bi| 的边。
bi>0 同理,只不过是出点向 T 连。
那么现在只需要刻画有限制的边了,注意到一条边意味着两个点需要在同一集合,所以这条边应当是不可割的,设为 inf。
对于边的节点,限制可以拆成如 u∈S→v∉T 和 u∈T→v∉S 的若干并列子限制。对于 v∈T→u∉S,可以看成 u∈S→v∉T,这样就只剩一种形式的限制了,而这种形式是容易刻画的,将 u 的出点连向 v 的入点,意为如果 u∈S 则必须断开 v 的出点与 T 的边。
于是就做完了,最小割转最大流就好了。
P6821 [PA2012] Tanie linie
首先每次选的一定是极长同号段。那么不考虑选的个数的限制,全选正数段时最优的。那么现在是有若干个段,要合并 or 不取一些。
对于一个正数段,不取的代价是 ai;对于一个负数段,取的代价是 |ai|。然后考虑反悔贪心。
注意到取会和两端的取合并,这样如果不取这一段了可以把负数多算的贡献减掉。
注意到不取会和两端的不取合并,这样如果取了这一段了可以把正数多算的贡献减掉。
注意到最两端的负段是不能算的,那么这样就可以过了。
P7324 [WC2021] 表达式求值
如果是我遇到这个题,肯定会每一位单独考虑,然后使用神奇的任意值转 01,注意到只有 10 个数,状压枚举即可。
然后是表达式求值,那么写一个。然后就不会了。
实际上就是任意值转 01,分成小于和大于等于。但我们最后要求的是等于,怎么办?容斥一下。
对于数 ai,比他小的数为集合 S,那么它的贡献就是 fS−fS+i,观察一下发现确实把多出的贡献减掉了。
那么就做完了,O(2m|E|+nm)。
P7323 [WC2021] 括号路径
牛啊。
推推性质,发现如果有 (u,v) 那就有 (v,u)。如果有 (p,q),(q,r),那就有 (p,r)。
观察样例,发现如果有边 <u1,v,w> 和 <u2,v,w>,就能产生 (u1,u2),相当于这两个点缩点了。
那么模拟缩点即可,之后就是每个连通块内的点两两可达。
P4714 「数学」约数个数和
挺有趣的题。
令答案为 fk(n),注意到 fk(n)=∑d|nfk−1(d),f0(n)=σ0(n),容易发现 fk=fk−1∗1,即 fk 为积性函数。
那么就有 n=m∏i=1pcii,就有 fk(n)=m∏i=1fk(pcii),考虑如何计算 fk(pc)。
注意到 fk(pc) 的值与 p 无关,因此只需考察 gk(c)=fk(pc),p∈P 即可。
容易发现 gk(c)=c∑i=0gk−1(c),g−1(c)=[c=0],这样就可以 O(ck) 计数了。
考虑其组合意义,发现其实就是 (−1,0) 走到 (k,t∈[0,c]),每一步只能走 (0,1) 或者 (1,1)。
可以认为 (1,1)=(0,1)+(1,0),那么枚举 t 剩下的就是一个组合数问题了,计算是暴力的,复杂度就变成 O(c2) 的了。
分解质因数考虑使用泼辣的肉,那么就过了。
P3312 [SDOI2014] 数表
实际上是求 n∑i=1m∑j=1σ1(gcd(i,j))[σ1(gcd(i,j))⩽a],多组询问。
先扔掉 a 的限制,化简易得为 n∑q=1⌊nq⌋⌊mq⌋(σ1∗μ)(q)。
考虑 a 的限制,相当于就是按照 σ1 从小到大激活,容易发现激活的贡献次数在狄利克雷卷积上是 O(nlogn) 的,暴力激活即可。
统计答案就是数论分块前缀和了。狄利克雷卷积前缀和可以拿树状数组维护,复杂度 O(q√nlogV+VlogV)。
CF1750F Majority
很牛的前缀和优化。
首先推一些性质,观察到一个串在操作至不可操作后,一定只有一种状态。
如果该串合法,则一定两个端点为 1,且每个 0 段的长度严格大于相邻两端 1 段长之和。
那么,考虑记 fi,j 表示长为 i,操作至不可操作后末尾 1 段长为 j 的合法串数量。
容易发现有 fi,i=2i−2−i−1∑j=1fi,j,fi,j=fj,ji−j−1∑k=j+2k−j−1∑l=1fi−j−k,l。这样算是 O(n4) 的。
注意到求和的限制其实是 j+k<i,j+l<k,考虑用 i−j−k+l<i−2j 刻画 j+l<k,同时动态维护所有 j+k⩽i 的 f 的和 sumi,则可以优化式子为 fi,j=fj,jsumi−2j−1,复杂度 O(n2),可以过。
P2480 [SDOI2010] 古代猪文
求 g∑d|n(nd)mod999911659。
注意到 999911659 是一个质数,那我们就只要求 ∑d|n(nd)mod999911658。
注意到 999911658=2×3×4679×35617,可以对每一个质数分别求,然后 crt 合并。
那么就是求 ∑d|n(nd)modp,那就是枚举因数 lucas 组合数,那就做完了。
CF1442D Sum
首先注意到至多只有一个序列不会选满,因为如果有两个没选满,一定可以舍小选大而不改变选的总数,直到选满。
那么就可以枚举没选满的位置,然后剩下的就是整段的背包了。
但这样是 O(n2k) 的,过不了。
注意到可以使用经典套路分治来优化,若要递归到 [l,m] 的时候就做一遍 [m+1,r] 的背包然后回溯递归,这样就可以优化到 O(nklogn),可以过了。
P7118 Galgame
首先发现答案形如以下,设卡特兰数为 Hn,那么答案计算如下:
- 首先加上 szrt−1∑i=1Hi。
- 对于每一个节点,加上左子树未满的贡献是 szlsu−1∑i=0HiHszu−i−1。
- 然后往左边走,乘上系数 Hrsu;往右边走,乘上系数 1。
注意到此时复杂度不对,第二步是 O(n2) 的。
注意到我们可以把这一步的复杂度从 O(szlsu) 降为 O(min(szlsu,szrsu)),这样复杂度就变成了启发式合并的 O(nlogn) 了!
愿称之为 lyc 大 trick。
P8421 [THUPC2022 决赛] rsraogps
首先离线询问扫描线。
注意到扫描线时对于三个维度的任意一维,每次只会改变一段后缀,并且每一个维度总改变次数均为 O(nlogn)。
那么就可以暴力找出修改的位置。然后前缀和就好了。维护的时候直接维护前缀和就好了。
AT_agc001_e [AGC001E] BBQ Hard
原式子不好求,因此考虑转化。
注意到 (a+ba) 具有组合意义,为 (0,0) 走到 (a,b) 方案数,且本题值域较小,可以往这边想。
那么 (ai+bi+aj+bjai+aj) 就可以看成是 (−ai,−bi) 走到 (aj,bj) 的方案数。
那么现在就可以直接算了,在网格里 dp 即可,复杂度 O(V2+n)。
AT_agc056_c [AGC056C] 01 Balanced
注意到差分约束是好想的。维护前缀和,那么就有以下限制:
- si−si−1∈[0,1]。
- sr−sl−1=r−l+12。
但是这么做有负权边,要用 spfa,复杂度不好。
注意到主要是第二类边导致的负权边,因此可以考虑构造 ti=2si−i。
这样的话,限制就变成了:
- |ti−1−ti|=1,即 ti−ti−1⩽1,ti−1−ti⩽1。
- tr−tl−1=0。
- ti≠ti−1。
第三类限制看似难以处理,但是注意到图是一张关于点编号奇偶性的二分图,因此某点最短路奇偶性与点编号奇偶性一致,所以是一定成立的。
那就全都是正权了,甚至是 01 边权的,可以 01bfs。
CF1608F MEX counting
经典留空 trick,可惜我已经忘了。
考虑从前往后 dp。设 fi,j,k 表示前 i 位,前缀 i 的 mex 为 j,前面有 k 种(不考虑是哪 k 种,仅仅是值域上的占位符)比 j 大的数的方案数。
若不改变 mex,容易发现存在以下转移:
- 填的比 mex 小:fi,j,k×j→fi+1,j,k。
- 填的比 mex 大,且之前出现过:fi,j,k×k→fi+1,j,k。
- 填的比 mex 大,且之前没出现过:fi,j,k→fi+1,j,k+1。
若改变 mex,则当前位一定填 mex,枚举 mex 变成了多少,则有:
- fi,j,k×At−j−1k→fi+1,t,k−(t−j−1)。
这样转移复杂度是 O(n2k2),冲不过去。
注意到复杂度最爆炸的地方是改变的情况,考虑加速这个转移。
fi,j,kk!(k−t+j+1)!→fi+1,t,k−t+j+1,即 fi+1,t,k′=∑j<tfi,j,k′+t−1−j(k′+t−1−j)!k′!。
注意到右边的 f 下标第二维和第三维和为定值,可以考虑使用前缀和优化。
具体地,令 gi,j,k=∑j′⩽j,j′+k′=kfi,j′,k′k′!,那么就有 fi+1,t,k′=gi,t−1,k′+t−1k′!。
复杂度降至 O(n2k),可以通过。
P4151 [WC2011] 最大XOR和路径
找一条路径,可以重,考虑环的影响。
如果现在有一个当前答案,有一个环,那你可以从一个点走到环,走一圈环,走回来,恰好会计入环的贡献。
因此就是找一条任意 1→n 的路径,然后线性基插环。
枚举所有环,考虑建一棵生成树比如 dfs 树,然后对于每一条非树边计算这个环的贡献。
容易发现大环的贡献是会被算进去的,那么就做完了。
AT_agc043_d [AGC043D] Merge Triplets
观察到如果一个块中有 ai>ai+1,那么在 p 中值 ai 后面一定紧跟 ai+1。
因此,p 一定可以分成若干个长度小于等于三的极长降序段,且段与段之间保持段头升序。
注意到段都是由块分裂而来的,因此长为 1 的段一定不少于长为 2 的段。
考虑令 fi,j 表示用 [1,i] 的数填到 p 中 [1,i] 的位置,且 1 段数量与 2 段数量之差为 j 的方案数。那么答案就是 ∑j⩾0fn,j。
考虑转移,枚举下一个段长度:
- 若长为 1,那就是段 [i],即 dpi,j←dpi−1,j+1。
- 若长为 2,那就是段 [i,b<i],即 dpi,j←dpi−2,j−1×(i−1),相当于是将原值域中 ⩾b 的数全部 +1 以保证正确,枚举不重不漏,类似于排列计数的那种 trick。
- 若长为 3,那就是段 [i,b<i,c<i],即 dpi,j←dpi−3,j×(i−1)×(i−2)。
P7735 [NOI2021] 轻重边
注意到修改一条链会对这条链上的所有出边赋为 0,链上的所有边赋为 1,难以维护,考虑构造一种关系转化。
给每个点赋一个颜色,同色为 1,异色为 0。那么修改就是把链染色,查询就是简单的,树剖线段树维护就做完了。
CF1264D2 Beautiful Bracket Sequence (hard version)
注意到一定有且仅有一个位置满足 pre=suf=k,因此可以枚举这个位置。枚举深度为 j,则方案数就是 (pj−p′)(sj−s′),其中 p,s 为 ? 前后缀和,p′,s′ 分别为 (,) 前后缀和。
这样算复杂度是 O(n2) 的,考虑优化 ∑jj(pj−p′)(sj−s′)。
注意到 ∑jj(pj−p′)(sj−s′)=∑j(j−p′)(pj−p′)(sj−s′)+∑jp′(pj−p′)(sj−s′)=p∑j(p−1j−p′−1)(sj−s′)+p′∑j(pj−p′)(sj−s′)=p(s+p−1s+s′−p′−1)+p′(p+ss+s′−p′)。
复杂度降至 O(n),可以过。
CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
dsu on tree
字符集大小很小,给每个字符赋权,考虑用桶维护状压,一条链合法当且仅当 w=0∨w=2k,链的拼接就是异或。
此时暴力的复杂度是 O(n2) 的。
考虑树上启发式合并,每次先做轻儿子的子树答案。做完后再做重儿子的,同时保留重儿子的桶的信息,再将轻子树的贡献一个个加到桶里并合并答案,这样复杂度是 O(nlogn) 的。
总时间复杂度 O(|Σ|nlogn),空间复杂度 O(cn+2|Σ|)。
P10778 BZOJ3569 DZY Loves Chinese II
动态判断连通性,但是操作互相独立。
相当于我们要找出所有割集,然后看询问的边集是否包含某个割集。
使用神秘的边权随机赋权满足每个点的边边权异或和为 0,容易发现是可以快速建的,建法是拉出一棵生成树,非树边随机赋,树边定向赋使得条件满足。
在这种做法下,一个边集是割当且仅当边权异或和为 0。考虑证明,设我们将点集 S 与其他点存在不连通,归纳证明。
若 |S|=1,即我们要把他所有边割去,满足要求。若 |S′|=k+1 且 |S|=k 满足要求,S′=S+u,也就是将 u 扔进去,由于异或,<u,v>,v∈S 的边边权会少算两遍,恰好抵消,因此异或和还是 0。
在随机情况下,正确性得以保证。那判断连不连通就可以直接用线性基线性判断了。
长链剖分
就是每次选择最深的儿子为长儿子。
以询问 x 的 k 级祖先为例,普通重链剖分是 O(n)∼O(logn) 的,倍增是 O(nlogn)∼O(log) 的。
长链剖分可以做到 O(nlogn)∼O(1)。
首先,长链剖分。预处理每个节点的 2k 级祖先。预处理每条链的信息,具体地,若这条链长为 l,则在链顶处记录所有 i∈[0,l] 级祖先和孩子。
查询时,先跳到 x 的 2lgk 处为 y,令 k′←k−2lgk。注意到由于是长链剖分则有 2lgk⩽leny,又 k′<2lgk,就有 k′<leny,那么直接跳到这条链的链顶,然后 O(1) 查找就行了。
P3768 简单的数学题
做法一:注意到 gcd(i,j)=∑d|gcd(i,j)φ(d)=∑d|i,d|jφ(d),则原式可以化简为 n∑d=1φ(d)d2(⌊nd⌋∑i=1i)2.
做法二:注意到可以化简为 n∑g=1g3⌊ng⌋∑d=1μ(d)d2(⌊ndg⌋∑i=1i)2。令 t=gd,则可以化简为 n∑t=1t2(⌊nt⌋∑i=1i)2∑d|tid(td)μ(d)。注意到 ∑d|tid(td)μ(d)=φ(t),则可以化简为 n∑t=1t2φ(t)(⌊nt⌋∑i=1i)2。
无论哪种做法化出的式子都一致,使用杜教筛即可。
P6478 [NOI Online #2 提高组] 游戏
和期望一点关系都没有,就是求合法点对恰为 k 的方案数。
本质上就是一个人是 p,pi=i,另一个人是排列 q,合法点对数量就是 pi 与 qi 匹配的数量。
发现恰好不好搞,转化为至少,那么 gk=n∑i=k(ik)(−1)i−kfi。转化为求 f。
令 dpu,j 是子树 u 中选了 j 个合法点对的方案数,计算是容易的,不难发现 fk=dpu,k×(n2−k)!。
那么就做完了,复杂度 O(n2)。
P3181 [HAOI2016] 找相同字符
我们不会做字符串之间的答案,但我们会做同一字符串内的匹配,那么可以把答案写成 calc(A#B)−calc(A)−calc(B).
在同一字符串内匹配,先求出 height,那么匹配的过程类似于单调栈,直接维护即可。
P2408 不同子串个数
注意到不同子串个数为 (n+12)−∑hi。
P3975 [TJOI2015] 弦论
注意到 t=0 类似于上题,按顺序遍历 h 就是按字典序枚举的,每个位置的贡献是 n−sai−hi+1。
来到 t=1,可以对 h 建一棵笛卡尔树,那么就是先序遍历这棵树,节点贡献为 [l,r]×(hf,hu]。对于原序列两两之间的空隙 (i−1,i),令 f′ 为遍历到这个空隙的直系父亲,则空隙贡献为 n−sai−hf′+1。
那么就做完了。
P5445 [APIO2019] 路灯
注意到如果动态记录每一个 0 的位置集合 s,那么 [l,r] 合法当且仅当存在 [a−1,b]⊆[i,nxti],i∈s。
考虑离线二维数点,对于每一个 [i,nxti] 建立点 (i,nxti,t),权值 ±1,那么查询的答案就是一块矩形的和,cdq 分治即可。
注意到一个点 u 对 t 的询问贡献为 wu×(t−tu),因此需要维护 ∑w 和 ∑wt 的和。
P10639 最佳女选手
注意到就是吉司机线段树,维护三种加标记,分别对于最大值,最小值,和平凡值即可。
节点维护该维护的就好了,注意常数。
唉,O(nlog2n) 的题开 5e5,什么素质。
AT_arc137_e [ARC137E] Bakery
很棒的网络流题目。
建模与志愿者招募很像。
大概有两种存在细小差异的建模方法:
- 钦定所有面包都被做了。钦定最大流为 ∞,则建边 (i−1,i,ai,x),(i−1,i,∞−ai,0),对于师傅建边 (l−1,r,1,c),跑 0→n 的最小费用最大流即可,答案为 x∑a−cost。复杂度是惊人的 O(nmlogm),在只加了 SLF 优化的普通费用流就能过。
- 钦定所有师傅都被选了。建边 (i−1,i,ai,x),(i−1,i,∞,0),对于师傅建边 (S,l−1,1,0),(l−1,r,1,c),(r,T,1,0),跑 S→T 的最大费用最大流即可,答案为 cost−∑c。复杂度是惊人的 O(bomb),过不了。
P3688 [ZJOI2017] 树状数组
注意到这个很牛的树状数组实际上是一个很对的求后缀和的东西,因此询问就是判断 al−1==ar 的概率,当 l=1 就是判断 r 的前后缀和相等的概率。
对于 al−1==ar,由于 l−1 和 r 不互相独立,因此开一棵二维线段树记录所有点对的答案。
那么对于修改 [l,r],分情况讨论:
- 对于 (x,y),x∈[1,l),y∈[l,r],相等性改变的概率是 1len。
- 对于 (x,y),x∈[l,r],y∈(r,n],相等性改变的概率是 1len。
- 对于 (x,y),x,y∈[l,r],相等性改变的概率是 2len。
使用标记永久化的区间修改单点查询二维线段树即可。
对于 l=1,额外开一棵一维线段树。对于修改,进行讨论:
- 对于 x∈[l,r],x 前后缀和不改变的概率为 1len。
- 对于 x∈[1,l)∪(r,n],x 前后缀和不改变的概率为 0。
总复杂度 O(nlog2n),卡卡时间和空间可以轻松通过。
至此,一锤定音。
尘埃,已然落定。
AT_arc114_e [ARC114E] Paper Cutting 2
除了第一步全都想到了,唉。
注意到每次修改矩形之后概率会改变难以计算,因此考虑转换操作。
每次选一条线,选完之后不删除,如果下一次选到了不合法的线就当做是重新再选一次。
那么这样的话每条线在任意时刻被选中的概率都是相等的,就简单很多了。
将期望拆成概率,那么就是求每条线第一次被选中时的概率之和,可以简单计算,为(以 r 为例)∞∑j=0(u+d+l+is)j1s=1s−u+d+l+i。
那么就直接算就好了。
AT_arc114_f [ARC114F] Permutation Division
首先,k 越小越好,因为答案肯定不劣于原排列。
注意到若划分方案确定,那么 Bob 的重排方案仅仅为段头降序排列。
若 a1<k,则答案中第一位一定不为 a1,直接钦定段头为 1∼k 即可。
否则,答案与原排列一定会有一段公共前缀,设其长度为 l。
为了判断长为 l 的公共前缀是否存在方案构造,可以有如下观察:
- 首先,在 a[1,l] 中取出一段下降子序列 {apm} 且 p1=1。
- 统计 a[l+1,n] 中小于 apm 的数数量为 c,若 m+c⩾k,则 l 合法。具体地,就是把那些选出来的数全部当段头。
快速判断可以使用树状数组做到 O(nlogn)。
判断出 l 后,剩下的就简单了,在 a[l+1,n] 中取出前 k−m 小的数当段头即可。
AT_arc114_d [ARC114D] Moving Pieces on Line
对颜色在数轴上进行差分,那么其实要求最终有 n 个差分点(A 类点),一个棋子就是在 ai 放一个差分点 (A 类点),同时可以在任意位置放一个差分点(B 类点)。同一位置两个差分点抵消。我们需要将每一个 A 类点与某个 B 类点匹配,同时 B 类点可以相互匹配,每个 B 点需要恰好匹配一个点。
那么就可以二维 dp 了,令 fi,j 表示考虑了前 i 个 A 类点与前 j 个 B 类点的最优答案。考虑转移:
- B 类点相互匹配:fi,j+2←fi,j+|Bj+2−Bj+1|。
- A 类点与 B 类点匹配:fi+1,j+1←fi,j+|Bj+1−Ai+1|。
复杂度 O(n2),可过。
AT_arc145_c [ARC145C] Split and Maximize
很好玩的数学题,注意不要读错题目。
首先把 2i−1,2i 看成同一种颜色,那么就是要求序列能分成两个子序列使得这两个子序列在颜色层面上完全相同。
那就直接拿颜色做好了,最后答案乘上 2n.
一种简单的分序列想法是每种颜色第一个放到 A 中,第二个放到 B 中,这样给定原序列可以生成唯一的划分方式 A 和 B,这样计算划分方式就和计算原排列等价了。
考虑怎样的序列合法,首先要有 A=B,其次为了满足第一个 A 第二个 B 的限制,也即任意 i 满足 pos(Ai)⩽pos(Bi)。将 A 看成左括号,B 看成右括号,那么原序列需要是一个合法的括号序列。
枚举 A 是什么,再算出 A 与 B 的组合方式为卡特兰数,就好了。
答案就是 2n×n!×Hn=2n(2n)!(n+1)!。
AT_arc145_d [ARC145D] Non Arithmetic Progression Set
牛死了。
注意到我们如果构造出了任意和的长为 n−1 的方案,通过微调就可以满足题目要求。
考虑怎么构造。方法有三:
- 差分,构造差分数组为 1,2,1,5,1,2,1,14,1,2,1,5,1,2,1,42,⋯,容易发现这就是卡特兰数,因此可以证明值域在上界之内。
- 选用那些三进制表示下只有 0,1 数码的数,因为这样 x+z=2y 的右边只含 0,2,若要左边也只含 0,2 当且仅当 x=z,符合要求。
- 暴力打表,打出 10000−1 个数,宽松的 AtCoder 允许我们把表交上去。
AT_arc145_e [ARC145E] Adjacent XOR
牛死了。
注意到 ai←ai⊕ai−1 的逆运算是 ai←⊕ij=1aj,因此转换题意与操作,用 b 生成 a,这样就简单多了。
注意到若 ai 不在 b[1,i] 的线性基里,则不存在答案。否则一定存在,可以构造。
由于一次操作会影响前缀,考虑从后往前逐位钦定。
在钦定 bi 时,考虑将 b[1,i] 插入线性基 p 中,同时令 ci=st(⊕j∈stpj=bi),不难发现在 b 上钦定与在 c 上钦定是等价的,本质就是换了一组基。
将 ai 也变换一下为 a′i。注意到线性基的优势为操作低位时不会影响到高位,因此可以以时间顺序从后往前依次钦定每一位。本质上就是将所有二进制位的出现顺序排了一个序,先出现的不会影响后出现的。
钦定第 j 位时,具体地,为当前 ⊕ik=1ck 的第 j 位与 a′i 的第 j 位不同,我们要让这一位出现的数量恰好改变奇数次,比如为 1。找到它在 ci 中第一次为 1 的位置 k,那么对 k+1 做一次操作,便可以满足要求。
钦定完成后,对 i 做一次操作,使用前缀和巩固革命成果,接着继续钦定 i−1。注意当 2 被钦定后便可结束。
操作次数 nlogV⩽7e4,复杂度 O(n2logV)。
AT_arc111_c [ARC111C] Too Heavy
场上没有意识到我的做法就是最小的,破防了。
首先判无解,当且仅当 i≠pi∧ai⩽bpi。
然后,这种排列的问题,往置换环上想。在置换环上找到最强壮的人,让他承担所有交换,做一遍置换,就好了。容易发现这样的交换次数是达到理论下界的,因此就好了。
UPD:直接乱序做也能过,正确性证明未知。
UPD:正确性证明:考虑如果在环上任意两点进行交换只要交换合法,一定会让环的数量 +1,因此正确性就好了。
AT_arc111_f [ARC111F] Do you like query problems?
超级牛逼题。
注意到,对于一个操作是询问,它对于答案的贡献是 n∑i=1i(n−i+1)ai。
令 fi,j 表示已经进行了 j 个操作,所有情况的 ai 的和,那么答案就是 n∑i=1i(n−i+1)q∑j=1fi,j−1(n(n+1)2×(2m+1))q−j。
考虑计算 fi,j。分类讨论:
-
若 j 是一个询问,那么 fi,j←fi,j−1×n(n+1)2。
-
若 j 是一个修改。首先有一个超级牛逼观察,注意到如果操作是 v,那么对于操作是 min,max 两种情况,这两种操作以后 a′i 的和为 v+ai。
那么 fi,j←fi,j−1×i(n−i+1)×m+(n(n+1)2×(2m+1))j−1×i(n−i+1)×m(m−1)2+fi,j−1×(n(n+1)2−i(n−i+1))×m×2。
综上,令 ci=i(n−i+1),则 fi,j=fi,j−1×((n(n+1)2−ci)×m×2+ci×m+n(n+1)2)+(n(n+1)2×(2m+1))j−1×ci×m(m−1)2。
令 t=n(n+1)2×(2m+1),r=(n(n+1)2−ci)×m×2+ci×m+n(n+1)2,d=ci×m(m−1)2,都是仅与 i 有关的常数。
化简原式为 fi,j=fi,j−1×r+tj−1×d,答案为 n∑i=1ciq∑j=1fi,j−1tq−j。
考虑对于同一个 i 快速计算 q∑j=1fi,j−1tq−j=1tq−1∑j=0fi,jtq−j 的值。
令 gi,j=fi,jtq−j,则 fi,j=gi,jtq−j,原式为线性求和。递推式转为 gi,j=rtgi,j−1+tq−1d。
可得 gi,j=j−1∑k=0(rt)ktq−1d=tq−1d(rt)j−1rt−1。
则 1tq−1∑j=0fi,jtq−j=q−1∑j=0tq−2d(rt)j−1rt−1=tq−2dq−1∑j=0(rt)j−qrt−1=tq−2d(rt)q−1rt−1−qrt−1。
那么就做完了。
P5327 [ZJOI2019] 语言
题目就是要对于每一个点求出它能走到的点的集合大小。
注意到对于每一个点相当于是在将一些集合取并集,考虑如何刻画。
转换成线段树上的区间覆盖,那就是问有多少点有值,那就好做了。
但我们不可能对所有点都暴力插入 mlogn 个区间,太慢了。
由于一条链修改的是一条链,那么可以转化成树上差分,然后全树前缀和也就是线段树合并。
那么就做完了,空间巨大。
AT_arc151_e [ARC151E] Keep Being Substring
无语了。调了 inf 年。
注意到如果两个串有 lcp > 0 那么答案就是 |S|+|T|−2lcp。这一部分 SA 算最长公共子串即可。
否则一定是先把 S 删到只有一个字,然后变这个字,然后变成 T。按照题意对 ai−1,ai 建边即可,边权为 2。那么答案就是 |S|+|T|−2+dis。
单位根反演
核心式子:[n∣k]=1nn−1∑i=0ωikn。
证明:若 n∣k,则 ωkn=1,1nn−1∑i=0ωikn=1nn−1∑i=01=1。若 n∤k,则 1nn−1∑i=0ωikn=1n⋅ωnkn−1ωkn−1=0。
推论:若 degf=m,则 m∑k=0[n∣k][xk]f(x)=1nn−1∑i=0f(ωin)。
证明如下:
AT_arc145_f [ARC145F] Modulo Sum of Increasing Sequences
首先令 bi=ai+i−1,那么问题就变成了在 [0,M=n+m−1] 上选择 n 个数了,并且和模 p 为 k。
首先有选数的生成函数 F(x)=M∏i=0(1+xi)。
如果不考虑选择 n 个数的限制,那么答案就是 ∑p|i−k[xi]F(x)。
施加之以单位根反演,得 ∑p|i−k[xi]F(x)=M∑i=0[p∣i−k][xi]F(x)=M∑i=01pp−1∑j=0ωj(i−k)p[xi]F(x)=1pp−1∑j=0F(ωjp)ω−jkp。
即求 1pp−1∑j=0ω−jkpM∏i=0(1+ωijp)。
先考虑 p∣M+1 的情况。令 d=gcd(p,j),t=M+1p,则有
trick:分圆多项式 xn−1=n−1∏i=0(x−ωin),证明就是右边是零点式。
令 x=−1,得 1−(−1)n=n−1∏i=0(1+ωin)。
代入上面的式子,得到答案 1pp−1∑j=0ω−jkpM∏i=0(1+ωijp)=1pp−1∑j=0ω−jkp(pd−1∏i=0(1+ωijpd))dt=1pp−1∑j=0ω−jkp(pd−1∏i=0(1+(ωjpd)i))dt=1pp−1∑j=0ω−jkp(1−(−1)pd)d(M+1)p。
考虑处理掉 ω,枚举 d,可得原式为 1pp−1∑j=0ω−jkp(1−(−1)pd)d(M+1)p=1p∑d∣p(1−(−1)pd)d(M+1)p∑gcd(p,j)=dω−jkp。
施加之以莫反,得
最后一步是单位根反演逆用。
发现这个式子中的 p,k 都是不变量,因此可以对于所有的 d 预处理出这个式子的值,设为 g(d)。
则答案为 1p∑d∣p(1−(−1)pd)d(M+1)pg(d)。
此时我们还没有考虑长度为 n 的限制,考虑加入这个限制。
令 F(x,y)=M∏i=0(1+xiy),类似于上文的推导,可以得出长度为 n 的答案为 [yn]1p∑d∣p(1−(−y)pd)d(M+1)pg(d)=1p∑d∣pg(d)[yn](1−(−y)pd)d(M+1)p。
注意到只有当 pd∣n 时才有贡献,直接二项式定理展开计算即可。
那么对于 p∣M+1 的情况就可以在 O(p2) 复杂度内计算出来。
现在考虑 p∤M+1 的情况。
首先可以 O(p2) 算出只取 [0,p⌊M+1p⌋−1] 的方案数。
对于剩下的那部分,考虑使用暴力 dp 转移。
具体地,令 fi,j,k 表示在 [p⌊M+1p⌋,M] 取到了 i,取了 j 个,和模 p 为 k 的方案数。使用 O(p3) 暴力转移。
最后再枚举 j,O(p3) 暴力合并答案即可。
AT_arc108_e [ARC108E] Random IS
注意到 n 比较小,可以考虑区间 dp。
令 fl,r 表示强制选 al,ar 后,在 [l,r] 内还可以选的期望数。注意到这样做是对的,因为在全局合法中等概率取与在全局合法中等概率取到 [l,r],再在区间内取的概率是相同的。
那么就可以枚举选到了谁,写出转移式 fl,r=∑x∈[l,r],ax∈(al,ar)fl,x+fx,r∑x∈[l,r],ax∈(al,ar)1+1。
直接计算复杂度是 O(n3) 的,考虑优化。
使用树状数组存储 ∑fl,∗,∑f∗,r,以及合法的数的个数,可以优化至 O(n2logn) 就可以过了。
AT_arc108_f [ARC108F] Paint Tree
很棒的一道计数题。
大体思路是按照直径做。
首先找一条直径出来,两端分别是 u,v。
现将同色的 2n−1 种情况全部算掉。着重考虑异色。
求出每个点到两端的距离 d1,d2,枚举答案长度 l。若 l<min(d1,d2) 则不可能。若 l∈[min(d1,d2),max(d1,d2)),则只能被染成距离小的那个颜色。否则,两种颜色都能染。
直接计算即可,复杂度线性。
P2633 Count on a tree
区间求排名问题,考虑主席树。
注意到主席树求区间排名本质上就是做前缀和然后作差,那么做一遍树上前缀和,再作差就好了。
也就是询问的时候传进去四个线段树节点。
AT_arc121_d [ARC121D] 1 or 2
注意到选一个可以等价于和 0 匹配,那么原题目就是要我们两两匹配。
注意到匹配一定是当前最大和最小匹配,贪心最优性考虑邻项交换。
那么就是枚举放进去几个 0,复杂度 O(n2)。
AT_arc121_e [ARC121E] Directed Tree
容斥!容斥!容斥!容斥!容斥!
令 fu,j 表示子树 u 内有 j 个钦定位置填了钦定不合法的数的方案数。
容易得出 fu,j=j∑i=0fu,ifv,i−j。然后再加上根节点的贡献 fi,j←fi,j−1×(szu−1−(j−1))。
则答案就是 n∑j=0f1,j(−1)j(n−j)!。
AT_arc121_f [ARC121F] Logical Operations on Tree
做这种题,首先要确定合法判断。
为了使答案尽可能为 1,注意到可以先把所有 And 缩在一起,然后再缩 Or,使可以存在的 1 尽可能地被保留下来。
也即,答案为 1 当且仅当至少有一个 And 连通块值为 1。
发现至少有一个难以计算,正难则反,计算全部为 0 的方案数。
令 fu,0/1 表示以 i 为根的子树,i 所在的连通块值为 0/1 的方案数。考虑转移:
- 若边为 And,则正常合并 fu,0←fu,0fv,0+fu,1+fv,0+fu,0fv,1,fu,1←fu,1+fv,1。
- 若边为 Or,则子树不能为 1,即 fu,0←fu,0fv,0,fu,1←fu,1fv,0。
直接计算即可。
AT_arc151_f [ARC151F] RGB Card Game
超级牛逼大分讨。
注意到每个人的目的都是使自己的牌尽量少,因此如果能出牌一定会出牌。
考虑每一种情况都加以枚举。
-
只有一堆,数量分别为 A1,B1。
- A1≠B1,则谁小谁胜利。
- A1=B1,则看奇偶性,奇数 A 赢,偶数 B 赢。
-
有两堆,数量分别为 A[1,2],B[1,2]。
- 两堆都相同:发现两种颜色之间并无区别,可以合并成一堆,然后走只有一堆的分讨。
- 有一堆相同:设 A1=B1。以 A2>B2 为例,A2<B2 是类似的。此时 A 为了尽量快地出完,会先出 2,力图让 B 的 2 全部出完,然后 A 可以一次性全部出完 2;B 为了减速这种情况的发生,轮到他出牌时他会出 1。继续分讨:
- A1>min(A2,B2):此时 1 的数量可以支撑 A 把 B 的 2 全部出完。全部出完后,就只剩一堆了,根据这一堆还剩下的数量走只有一堆的分讨。
- A1⩽min(A2,B2):此时 1 的数量无法支撑 A 把 B 的 2 全部出完。在把 1 出完后,两人都只剩下 2,因此谁 2 少谁胜。
- 两堆都不同:继续分讨:
- 若 A1<B1,A2<B2:显然 A 抢夺天机,可以直接赢。
- 若 A1>B1,A2>B2:显然 B 抢夺天机,可以直接赢。
- 若 A1<B1,A2>B2:对于 A 来说,他只要尽快让 B 把 2 出完,就可以一次性清空自己的 2;对于 B 来说,他只要尽快让 A 把 1 出完,就可以一次性清空自己的 1。当某一种颜色出完时,局面转换成只有一堆的情况。因此,比较 A1 与 B2 的大小,若 A1⩾B2 则 A 赢,否则 B 赢。
-
有三堆,数量分别为 A[1,3],B[1,3]。
-
三堆都相同:注意到三种颜色存在区别,例子:A=B=[1,1,2],都先出颜色 3,轮到 B。此时 A=B=[1,1,1],若 B 出 1,则 A 可以不出,等到 B 出 2 了,A 出 2,出 1,出 3,胜。也即,最后可以保留一个 1 不打,因此奇偶反转,和为奇数 B 胜,和为偶数 A 胜。
-
有两堆相同:设 A1=B1,A2=B2,继续分讨:
- 若 A3<B3,则 A 赢。
- 若 A3>B3,则 B 赢。
因为如果 A=[1,1,A3],B=[1,1,B3] 时,会发现谁少谁就赢了。那么我们钦定的输的那个人要尽力使得 A1+A2 为奇数,那么对方可以镜像操作,直到输的那个人无法操作只能去出 3,于是谁少谁就赢了。
-
有一堆相同:设 A1=B1,继续分讨:
- A2<B2,A3<B3:发现就是谁少谁胜利。在 2 和 3 中取完某一堆后,一定可以转换到两堆的分讨,发现与 1 的大小密切相关。若 A 较小,此时 A 就可以无脑出 1。若 1 先被出完,则变成只有两堆,A 必胜局面;若 1 没有被出完,因为较小,也可以转换为 A 的必胜局面。若 A 较大,则可以通过控制 A 的奇偶性来决定胜负,显然 A 具有主动权,因此 A 是必胜的。
- A2>B2,A3>B3:发现就是谁少谁胜利。
- A2<B2,A3>B3:A 力图出 3,B 力图出 2,这是大体的策略。若 A2⩾B3(A2<B3 类似),则 A 在没有 1 的影响下就获胜了。现在考虑 1 的影响:
- 若 A2⩾A1+B3,也就是不管 B 怎么操作,A 只出 3,就能一直抢先他,因此 A 胜。
- 若 B3⩾A1+A2,也就是不管 A 怎么操作,B 只出 2,就能一直抢先他,因此 B 胜。
- 若上面两者都不满足,就会出现两个人都秒不掉对方的情况,只能一张一张牌慢慢出,也即会尽量保持堆数不变。因此答案与 A1+A2+B3 的奇偶性相关,奇数则 A 胜,偶数则 B 胜。
-
没有堆相同:继续分讨:
- A1<B1,A2<B2,A3<B3:A 抢夺了天机。
- A1>B1,A2>B2,A3>B3:B 抢夺了天机。
- A1<B1,A2<B2,A3>B3:A 会试图去让 B 出完 3,B 会试图让 A 出完 1,2,因此若 B3>A1+A2 则 B 胜,否则 A 胜。
- A1<B1,A2>B2,A3>B3:A 会试图去让 B 出完 2,3,B 会试图让 A 出完 1,因此若 B2+B3>A1 则 B 胜,否则 A 胜。
-
结束了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】