Cry_For_theMoon  

??怎么已经十月了???

1. Magic Matrix

首先意识到 \(a_{i,j}=a_{j,i}\) 是关键性质。

Solution 1:

\(d_{i,j}=\min\{\max\{a_{i,k},a_{k,j}\} \mid 1\le k\le n\}\),考虑求所有的 \(d_{i,j}\)

首先把 \(a\) 排序,考虑依次更新 \(d\)

发现可以 bitset 做到 \(O(\frac{n^3}{\omega})\)

Solution 2:

观察 \(a_{i,j}\le \max\{a_{i,k},a_{k,j}\}\)

\(a_{i,j}\) 看成图上 \(i\rightarrow j\) 的权值。

则等价于:任意一个三元环不存在严格最大值。

可以证明:其等价于任意一个简单环上不存在严格最大值。

证明:假设存在严格最大值,将简单环进行三角剖分即与三元环不存在严格最大值的条件矛盾。

然后最小生成树即可。

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

记录

2. Access Counter

感觉这个 G 不应该过这么多啊......

考虑设 \(w(i,j)\) 表示,上一次访问是时刻 \(i\),且下一次访问在时刻 \(j\) 的概率。

\(i\) 直接走到 \(j\),且 \((i,j)\) 这一段都不访问,恰好在第 \(j\) 个位置访问的概率,为 \(q\);转一圈都不访问的概率为 \(p\),那么概率是:

\[\sum_{i=0}^{\infty}p^i\times q=\frac{q}{1-p} \]

\(p\) 固定,枚举 \(i,j\)\(q\) 易求。

现在考虑设 \(f(i,j)\) 是访问了 \(i\) 次,且最后一次访问是位于 \(j\)(初始 \(f(0,23)=1\))的概率。

显然可以用 \(w\) 作为转移矩阵进行矩阵快速幂的优化。

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

记录

3. Tree nesting

如果这个问题给 \(T\) 定了根,就会简单很多(因为我们可以强制让 \(S\) 的根是 \(1\))。

不妨强制给 \(T\) 定根,有 \(m\) 种选择,去掉重构的部分;剩下若干棵树,现在等于算 \(\le m\) 次有根树的问题,以下皆默认 \(T\) 是有根树。

设:\(dp(u,v)\)\(S\) 中,以 \(u\) 为根的连通块,和 \(T\) 中, \(v\) 子树同构的数目。

\(u,v\) 的每对儿子 \((x,y)\),预先计算 \(dp(x,y)\)

现在,对于 \(u\) 的每个儿子,其有一个集合 \(A\)\(A\) 仅由 \(v\) 的儿子构成,且我们知道了从一个特定集合里选出一个特定元素的方案数(dp),现在,一个集合最多只能选一个元素出来,且要求最后选出的元素所构成的集合构成 \(v\) 的儿子的全体。

考虑状压:\(f(i,mask)\) 代表前 \(i\) 个点,选出的集合为 \(mask\) 的方案数。

这里需要去重:对 \(v\) 的所有儿子构成的子树划分等价类,对每个等价类 \(A\),显然答案除以 \(|A|!\)

时间复杂度大概在 \(O(n\times m^2\times 2^m)\sim O(n\times m^3\times 2^m)\) 左右,但注意到最大的 \(2^m\) 其实远远跑不到 \(2^{12}\) 这个级别,可以通过,实际效率还是很高的。

记录

4. kangaroo

签到题降智了...

把一个袋鼠视作线段 \([b_i,a_i]\),则你可以把袋鼠 \(i,j\) 组合当且仅当它们的线段不交。

则本质上一个袋鼠的组是若干条不交的线段,且最后你需要保证不能合并这样的两个组。

容易发现一个袋鼠 \(i\),所有 \(i\) 能塞进的袋鼠 \(j\),按照 \(b_i\) 降序排序的话,是一段前缀。

所以按照前缀长度重新排序得到数组 \(d_1,d_2,...,d_n\)

然后若 \(i\) 套进了 \(j\),等价于从 \([1,d_i]\) 里选出数 \(j\),一个数不能被选多次。

\(i\) 不套进任何一个袋鼠,体现在这里,就是说,\([1,d_i]\) 的数都被选完了。

考虑这个题支持三方所以设计 dp:\(dp(i,j,k)\) 表示前 \(i\) 个袋鼠,还有 \(j\) 个数是后面强制选掉的,除此之外,你还有 \(k\) 种选择。转移显然。

时间复杂度 \(O(n^3)\)

记录

5. Pikachu

绝世好题。

考虑这是一个类 huffman 编码的过程:我们将编码放到了 trie 树上,并且让深度浅的叶子对应了频率高的数。

回到本题,首先注意到,不同种类的边具有不同的权值,所以,不能保证深度浅的叶子对应频率高的数;但是,如果我们定义深度是根到该点的带权路径和,则上面的结论仍然成立:同时这启示我们按深度从小往大去 dp。

注意到深度不会太大,显然不超过 \(30\),考虑设 \(dp(depth,used,x,y,z)\) 是当前位于 \(depth\) 层,之前用掉了前 \(used\) 个数且当前层,下一层,下下层的现有节点个数为 \(x,y,z\)

枚举 \(depth\) 层分配的数的数目 \(cnt\),剩余的 \((x-cnt)\) 个节点,都会往 \(depth+2\) 层产生 \(2\) 个节点,往 \(depth+3\) 层产生 \(1\) 个节点。

计数的时候需要考虑到 \(a_i\) 重复的一些问题,总体时间复杂度 \(O(n^6)\)

记录

6. Euler

考虑 \(\phi(n)=\prod_{i=1}^{k}p_{i}^{a_i}\times \prod_{i=1}^{k}(p_i-1)\),其中 \(a_1,a_2,...,a_k\)非负整数。

设第一部分为 \(A\),第二部分为 \(B\),暴力枚举 \(A,B\) 则有 \(d(n)\) 种可能。

然后对 \(A\) 进行质因数分解,这样部分 \(p\) 就确定了;还剩下一些质数在 \(A\) 中贡献为 \(1\),在 \(B\) 中贡献为 \((p-1)\)

由于这些质数要求互不相同,直接爆搜即可,不会算复杂度。

记录

7. Replace

关键结论:若区间 \(p,q\) 有交,则 \(f(p\,\cup\,q)=f(p)\,\cup\,f(q)\)

进行任意次替换都满足这个结论。实质上是一种可合并性质。

首先考虑线段树维护,但注意到可以把 \(f(l,r)\) 拆成 \(r-l\) 个长度为 \(2\) 的区间的答案合并。

然后考虑倍增即可,显然不会跳跃超过 \(n^2\) 次,实现的时候只用到了 ST 表,非常厉害的题。

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

记录

8. Pebbles and Beads

真他妈,神仙牛逼题,没个 3000+ 我不是很认可。

首先这个题要是想怎么 dp 或者贪心就直接寄了。

考虑 \(\frac{\Delta A}{\Delta B}=-\frac{p}{q}\) 这个东西,两个 \(\Delta\) 的比值一定,直接让我们想到斜率

所以这个题应该有其几何意义:令 pebbles 的数量为 \(x\) 轴,而 beads 的数量为 \(y\) 轴,则我们可以把任意一个状态抽象成第一象限(或坐标轴上)的一个点。

加入一个操作,放在平面上考虑,等于是给出了一个线段,对于原有的点,可以沿着这条线段的方向继续移动不超过一定距离。

然后会发现我们只关注最外面一圈的轮廓,形成一个上凸壳!

然后考虑一个凸壳加入一条线段会发生什么,发现是一段前缀向上移动,剩余部分向下移动的形式,交界处加入这次插入的线段。

所以考虑 set 直接维护每条线段的斜率和长度即可。

然后维护起始点和终止点的坐标,加入线段后,动态调整,使得凸壳位于第一象限即可。

时间复杂度 \(O(n\log n)\),需要注意精度问题:考虑不存斜率而存一个整数的 \(\Delta x\)\(\Delta y\),把所有带斜率 \(k\) 的运算,都替换成带 \(\frac{\Delta y}{\Delta x}\) 的运算,就可以解决精度问题。

记录

9. Sum

首先注意到 \(A_i\) 这玩意的生成是毫无规律可言的,感觉在题目里放这玩意多少有点诈骗了......

然后这是一个经典的问题形式,考虑把左端点视作第一维,右端点视作第二维,则可以看成先进行若干次矩形加法,再进行若干次矩形求和。

首先通过二维差分/前缀和的手段,把矩形的左端点变成 \(1\),设右端点为 \((x,y)\)

考虑一个给 \((1,1)-(x,y)\) 全部加上 \(a\) 的操作,其等价于对于 \(x\) 坐标在 \([1,x]\) 的列,给第 \(i\) 列的 \([1,y]\) 这些位置加上 \(i\times a\);对于 \(x\) 坐标 \(\gt x\) 的列,相当于给 \([1,y]\) 这些位置加上 \(x\times a\)

所以关于列,是一个一次函数的形式,扫描线的过程中,用两个线段树分别维护一次项和二次项即可。

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

记录

10. 地震后的幻想乡

怎么模拟降智没有想出这么 ez 的题。

抓住题目给我们的 \(\frac{k}{n+1}\) 的提示,我们发现 \(E(\max\{a,b\})\) 无法很好地转成关于 \(a,b\) 独立的内容,所以只能从 \(m\) 条边全局来考虑了。

有一个 \(m!\times m\) 的做法:枚举最后边权的大小排列,然后知道了相对顺序,做 kruskal,最后加的是第 \(i\) 条边,则这种情况的贡献就是 \(\frac{i}{n+1}\),可以获得 50pts。

考虑我们基本上要把这个问题转成计数问题,结合上面的做法,可以想到,枚举 \(k\),使得加入前 \(k-1\) 条边整个图非联通,加入第 \(k\) 条边后整个图连通的概率。

此时概率就是离散而非连续的了,因为可能的边权大小的排列数目是确定的,而边权大小排列确定后,\(k\) 就确定了(即 50pts 的做法)。

那么第 \(k+1\sim n\) 条边的顺序我们不关注了,而第 \(1\sim k\) 条边的顺序是受关注的,同时前 \(k-1\) 条边和第 \(k\) 条边还有区别存在,最后会得到概率是 \(\frac{ways}{\dbinom{m}{k}}\)

\(ways\) 是由边集和边构成的二元组 \((E,e)\) 数目,满足:

  • 加入 \(E\) 的边后,图不连通。

  • 加入 \(E\cup \{e\}\) 的边后,图连通。

现在问题变成了一个看上去很可做也比较熟悉的计数形式。

\(E\) 计数的话,是比较简单的:考虑设 \(f(i,S)\) 是从 \(S\) 的子图中选出 \(i\) 条边(无序)且不连通的方案数,\(f\) 可以 \(m^2\times 3^n\) 计算。

显然 \((E,e)\) 中,\(E\)\(f(k-1,S)\) 种可能。

现在考虑对 \((E,e)\) 计数:不妨对 \((E,e')\) 计数,代表说,加入了 \(e'\) 这条边依旧不连通,因为总的二元组数目此时就是 \(f(k-1,S)\times (m-k+1)\),而 \((E,e')\) 的数量和 \(f(k,U)\)\(U\) 是全集)有密切联系:注意到 \((E,e')\) 的数量就是 \(f(k,U)\times k\)

所以 \(ways\) 的计数就解决了。

时间复杂度 \(O(m^2\times 3^n)\)

记录

11. Traffic

降智 again

考虑缩点以后,变成 dag 两点可达性;众所周知这玩意只能平方,但是 \(3\times 10^5\) 不太能冲得过去:考虑题目里有一个约束没有用到,就是给出的图是平面图,换言之边是不相交的,然后我们死盯起点和重点不放:发现若对于一个点 \(u\) 能到达终点 \(v_1,v_2\),且中间有一个点 \(v_3\) 不能被 \(u\) 到达,则它不能被所有的起点经过,可以删去它。

把这些点删掉以后,把终点按照 \(y\) 排序,则一个起点能到的终点是一段区间,只需要记录,能到达的 \(y\) 最小的和最大的点即可,此时可以拓扑实现。

复杂度 \(O(n+m)\)

记录

12. Link

这次没降智,但是完全来不及写代码了。

第一,连的边一定是 \(1\rightarrow u\) 形式的,证明显然。

第二,考虑树上一个不合法的叶子 \(x\),必须连一条 \(1\rightarrow x\) 的边,然后它会令一些祖先合法,删去这些点。

重复这个过程,直到在树上的点都被覆盖过为止(算上初始就合法的点)。

现在考虑一个环上的问题:有一个 \(0/1\) 构成的环,一次操作可以让 \(k\) 个连续位置变成 \(1\),问让所有位置变成 \(1\) 的最少操作次数。

若是链,则该问题是容易的;考虑断环成链以后,维护倍增即可。

事实上还有更快的做法:随便找一个为 \(0\) 的位置,覆盖它的操作有 \(k\) 种可能;只要你确定了第一个操作,后面跑贪心最多跑 \(\frac{len}{k}\) 次,那么总复杂度是 \(O(k \times \frac{len}{k})=O(len)\) 的。

另外,删叶子往上的过程中,需要用并查集记录向上第一个未覆盖的树上节点。

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

记录

13. XOR Triangle

讲真,虽然这场 E 恶意搬题,但是整个比赛题目质量本身还是很高的。

显然是个找性质以后数位 dp 的题。所以我们来把 \((a,b,c)\) 合法转成更可做的东西。

发现 \((a\oplus b)+(b\oplus c)\ge (a\oplus c)\) 是一定成立的,因为 \(X+Y\ge X\oplus Y\) 这个肯定是对的;思考一下什么时候取等:当且仅当 \(X+Y\) 的每一位都不进位的时候才取等号,所以你的目的是,存在一个位置 \(i\),使得 \((a\oplus b)\)\((b\oplus c)\) 的这一位都是 \(1\)(那么可以推出 \((a\oplus c)\) 的这一位一定是 \(0\))。

然后还有另外两个轮换的条件,推出共三个这种形式的轮换的结论,就能数位 dp 了,复杂度 \(2^{9}\times n\)

记录

14. Recover the Tree

还是有点玄学的。

首先考虑对一个极小的连通块去构造:就是一个区间 \([l,r]\) 是好的,而其所有长度不为 \(1\) 的子区间都是坏的,如何构造?

显然 \(len=2\) 的构造平凡;\(len = 3\) 的时候无法构造,否则考虑这样构造:最大的放在中间,奇偶的分开,形如:\(...,3,1,maxvalue,2,4,...,\) 这样放。

容易发现对于所有 \(r'\lt r\) 的区间(长度不为 \(1\)),一定非法,因为必定有一个奇数一个偶数,那么就会跨越最大值的位置。

而对于所有 \([l'\gt l,r]\) 的区间,容易发现其也是非法的。

现在回到原问题。

考虑把好的区间按照长度排序,则最开始就是做上面我们提到的这个问题,做完以后,把这些位置视为一个点即可。

最后需要注意,当你处理一个询问 \([l,r]\) 的时候,你会把所有 \([l,r]\) 涉及的连通块拿出来视为点进行上述的连边处理;但是,考虑最外层的两个连通块,可能有一部分超出了 \([l,r]\),而你不能让这些超出 \([l,r]\) 的部分参与连边,所以需要特判一下。

然后可能有些情况你就不用合并了,比如 \([l,r]\) 已经属于了一个连通块;这也是有点理论支持在里面的:若 \(p,q\) 为两个交非空的好区间,则它们的交,并都是好区间,想到了以后证明显然;所以你可以比较放心地这样做。

时间复杂度 \(O(n^2)\),但我不知道为啥我跑的这么慢...

记录

15. General General

误入分类讨论深渊的话这个题可以写的很抑郁。

如果可用向量 \(\le 1\) 个的话这个问题是平凡的,另外注意到我们不会选两个共线向量;而我们知道两个不共线向量的线性组合可以唯一表示出任意一个点,在这里,很大概率线性组合的系数是整数:也就是说很大一部分情况你只需要两个向量就够了,当然比如说如果是一个 \((1,1)\) 和一个 \((-1,-1)\) 的向量结合那不能用整系数线性组合表示出一些点,比如 \((0,1)\);那么就需要第三个辅助向量进行调整;事实上,只有两个 \(45\) 度角向量不能用整系数表示出任意整点啊,而这个时候显然你只要添加一个水平或者竖直的向量,动一步就好了。

而如果确定使用了哪两个向量进行正交分解就变成了解二元一次方程组的问题。

单次时间复杂度 \(O(1)\) 2333。

记录

16. Become Big For Me

非常牛逼的题啊。

首先,我们容易想到,把一个数拆成若干质因子的形式,然后 \(\gcd\) 应该是每个质因数的指数要取 \(\min\);而 lcm 是每个质因数的指数要取 \(\max\)

用若干个 \(\max\) 的和/差表示出一个 \(\min\),这让我们想到 \(min-max\) 容斥!!

想到以后,首先不难写出:

\[\gcd(S)=\prod_{T\subseteq S}lcm(T)^{(-1)^{|T|-1}} \]

观察到题目里这个 gcd 就是值数最大值和次大值的和?那么套用 \(kth\) \(min-max\) 容斥可以得到题目里的 gcd 就是:

\[\prod_{T\subseteq S}lcm(T)^{(-1)^{|T|}(|T|-2)} \]

这样 \(n\le 14\) 的时候操作量和输出量都能符合限制了,但是 \(n\le 10^5\) 依然是巨大的。

这个时候可能需要知道一些前置结论才会有灵感:任何一个值域在 \(n\) 以内的集合 \(S\),其 \(\gcd\) 可以用一个大小不超过 \(\omega(n)+1\) 的集合的 \(\gcd\) 表示。

证明是容易的:随便挑选 \(S\) 中的一个元素,显然最后的 \(\gcd\) 是它的约数:考虑它的所有质因子,对于一个 \(p\),找到 \(p\) 的指数最小的集合里的数塞进去,显然最后大小不超过 \(\omega(n)+1\)

类似地,利用这种方法:随便选两个数 \(x,y\),然后考虑所有质因子 \(p\)(必须是二者中至少一个的约数),然后把 \(p\) 的指数里最小的和次小的拿一个放进 \(S\)

现在,你可以让集合大小不超过 \(16\) 了,但是还多两个数......

注意到如果有 \(p\) 恰好整除 \(x,y\) 中的一个,则你加入指数次小的就够了(因为肯定有一个指数是 \(0\)),这种情况贡献是 \(1\):我们就思考能不能让这样的情况总是出现 \(\ge 2\) 次。

最后的解决方法是这样的:如果有一个质因数 \(p\),在所有数里都出现了,那只需要选对应的指数最小的两个数,就能让答案不超过 \(14\);否则,每个质因子 \(p\) 不会全出现,所以考虑让 \(2\)\(3\) 成为恰好贡献 \(1\) 次的质因数即可。

时间复杂度大概不超过 \(O(n\log^2 v)\)

记录

17. Ela Goes Hiking

比赛的时候读错题想了好久,错过了上大分的绝佳机会(彩蛋:睡到 22:50才被叫了起来开打)。

根据规则,如果有一段形如:右-右-右-右-左,那么向左移动的这只蚂蚁会依次吃掉剩下所有向右移动的蚂蚁。

这启示我们,把整个蚂蚁的移动序列分成若干个“右-右-右-右-左”的段,对于末尾的一段“右-右-右-右...右”,由于向右走到头还会掉头,可以把最后一个蚂蚁视作向左的方向,计算概率的时候 \(\times 2\) 即可。

对于每一段蚂蚁,最后剩下的一定是最左边的那只蚂蚁,它的大小是这一段的蚂蚁数量,且方向一定向左。

然后考虑此时的合并过程,一定是第一只蚂蚁和第二只合并,他们的产物和第三只合并,...,依次类推。

假使你想让此时的第 \(i\) 只蚂蚁成功获胜,则要求:

  • \(i-1\) 只蚂蚁的总体积不超过第 \(i\) 只蚂蚁的。

  • \(j\ge i\) 只蚂蚁的总体积永远大于第 \(j+1\) 只蚂蚁的。

第一个约束,是容易的;第二个约束难以从组合角度出发,考虑设计一个 dp:\(dp(i)=\sum_{i\lt j\lt 2i}dp(j)\)\(dp(n)=1\) 即可。

时间复杂度 \(O(n)\),赛场写的太急,写了个 \(O(n\log n)\) 做法。

记录

18. Permutation Oddness

我觉得是很有趣的题。

排列 dp 的话,容易考虑设 \(dp(i,j)\) 是长度为 \(i\) 的排列,怪异度为 \(j\) 的方案数;但这样的话,我们发现难以转移,因为插空插一个进去的话,会让原排列的一段后缀往后移动,它们的贡献也会变化。

考虑只有 \(n\times m\) 的维度可能是记录不了完备的信息的。

然后有一个很神的地方:考虑把这个问题变成球放盒子,那么答案是它们的距离和;此时考虑从前往后扫描箱子,有点类似线头 dp 的想法,只用设 \(dp(i,x,y,j)\) 是扫描完了前 \(i\) 个球和箱子,剩下 \(x\) 个球没放入,\(y\) 个箱子没使用,当前的距离和为 \(j\) 的方案数。

这样就容易转移了,复杂度 \(O(n^3\times m)\)

更进一步地,我们发现 \(x=y\) 总是成立的,所以只需要多记录一个维度,复杂度 \(O(n^2\times m)\)

记录

19. 网络

感觉至少有三种角度去入手啊,这个题。

其一:不妨把一个值挂在路径以外的所有节点位置,通过树剖可以做到这个事情,然后 seg 每个节点开堆维护 + 懒惰删除即可 \(O(m\log^3 n)\),这个做法复杂度最劣但是实测效果极其恐怖。

其二:直接考虑 dfs 序,由此引出线段树套 treap 以及 kdt 两种做法,后一种做法时间效率比较优秀。

其三:整体二分,这样的话,相当于每次你不关注询问的具体权值了,然后在线加入/删除一些路径,询问对于当前点,是否存在一个路径,使得点不在该路径上。

那么也就是等价于问一个点是否在当前加入的所有路径上。众所周知树上路径加法可以做到单 log,如果事先离散化边权,复杂度就是 \(O(m\log^2 n)\) 的。

还有 sjc 和 miao22 的神秘单log做法,有空再补。

先放个树套树的 \(\log^2 n\) 记录先:link

然后是整体二分的做法:link

20. Flipping Coins 2

很恐怖的 well-known problems in China (among Poly Master...)

首先我们需要对这个过程有一个更直观的了解:放在环上考虑是一个不错的选择。

我们一共会执行 \(n\) 个操作,这 \(n\) 个操作的长度是确定的,只不过,由于先后顺序的不同,每个操作的起始位置有所不同。排列 \(p\) 的意义就是:给每个操作分配一个执行的时间,时刻 \(i(0\le i\le n-1)\) 执行的,会从位置 \(i\) 开始覆盖,所以可以认为排列 \(p\) 的值域就是 \([0,n)\)

然后我们就会意识到:每个硬币最后朝上的概率是均等的:因为很显然,你可以把执行顺序轮换,使得对于任意两个硬币 \(i,j\),让 \(i\) 朝上的安排方式,与让 \(j\) 朝上的安排方式形成一一对应。

所以我们只来研究一个确定的位置:\(n-1\),现在转变成一个计数问题:多少个排列 \(p\) 使得 \(n-1\) 被翻面了偶数次。

考虑如果第 \(i\) 个操作(\(A_i\))在时刻 \(p_i\) 被执行,它若想对 \(n-1\) 翻面就要有 \(p_i+A_i\ge n-1\) 也就是 \(p_i\ge n-1-A_i\)

\(B_i=n-1-A_i\),则变成了 \(\sum_{i=0}^{n-1}[p_i\ge B_i]=k\) 这样一个约束,这样看起来就可做很多了。

不妨把 \(B_i\) 降序排序,这样如果你钦定 \(i\lt j\)\(i,j\) 都满足 \(P\ge B\),你会发现 \(i\) 处可选的值是 \(j\) 处可选的值的子集,这是一个很自然会想到的想法。

我们发现我们无法计数:恰好 \(k\) 个位置满足 \(P\ge B\) 的排列数,自然地考虑容斥:钦定某些位置 \(P\ge B\),则根据上述的,\(B\) 排序后的良好性质,易得:设 \(f(i,j)\)\(B_1\sim B_n\) 选出了 \(j\) 个位置,钦定 \(P\ge B\),则有:

\[dp(i,j)=dp(i-1,j)+(n-B_i-j+1)\times dp(i-1,j-1) \]

\(f(k)\) 是恰好 \(k\) 个位置满足要求的排列,\(g(k)\) 是钦定 \(k\) 个位置满足要求的排列,显然 \(g(k)=dp(n,k)\times (n-k)!\)

然后求出了 \(g\) 可以在 \(O(n\log n)\) 的时间内反演出 \(f\),然后整个问题没有难度了。然而 \(g\) 的 dp 求法是 \(O(n^2)\) 的也是瓶颈所在。

后面就是最 hard 的部分了。

重新定义 \(dp(i,j)\)\(j\) 个位置不钦定的方案数,设 \(f_i(x)\)\(dp(i)\) 的生成函数,则有这样的形式:

\[f_i(x)=xf_{i-1}(x)+C_if_{i-1}(x)+xf_{i-1}'(x) \]

我认为使用 gf 的时候需要时刻明确我们要求的是什么:\(f_{n}(x)\)\(x^0\sim x^{n}\) 项系数。

我们会做的是一个要求很严格的形式:\(f_i(x)=xf_{i-1}'(x)+C_if_{i-1}(x)\),这个形式,迭代一次,就是给 \([x^k]\) 乘上 \((k+C_i)\) 这个东西。

所以我们就要把上面的转移往这个形式上凑,关键在于 \(x(f_{i-1}(x)+f_{i-1}'(x))\)

然后乘上一个 \(e^x\) 就可以变成我们会的形式了...

最开始的替换也是基于这个道理:你可以不替换,然后同样写成 gf 推,但是你发现最后你就是差一个 \(\times x\),然后无法凑成我们会的形式。

凑成 \(f_i(x)=xf_{i-1}'(x)+C_if_{i-1}(x)\) 的形式以后,多项式多点求值即可。

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

记录

21. 填树

我大概是场上唯一得分 28 而不是 40 的选手...

首先需要说一下这里“所有情况的和之和”的一个计数方式,设方案数为 \(f\) 和为 \(g\),那么每次合并应该是:\(f=f_1\times f_2,g=f_1\times g_2+g_1\times f_2\) 啊,当时这个都不会,有点难蚌。

然后首先枚举最大值 \(a\),这个每个点的可取值范围是确定的,可以做一个 \(O(n)\) 的树形 \(dp\):大概就是 \(f(i,0/1)\) 表示以 \(i\) 为 lca 选一条路径且是否有点的值为 \(a\) 了,这个 \(O(n\times \max R)\) 的做法可以得到 40 分的分数。

把转移式子写出来发现每个点的贡献是个关于 \(a\) 的分段函数,分个四段左右的样子,对于一段 \(a\) 来说显然函数解析式是不变的,显然一条长度为 \(len\) 的路径的方案数此时是一个关于 \(a\)\(len\) 次函数,想到拉格朗日插值!因为我们要求的是前缀和,无非就是次数 \(+1\) 罢了。

考虑第二问求和是否有相同性质,事实上一条长度为 \(len\) 的路径的所有情况的答案和,不过是关于 \(a\)\(len+10\) 次函数罢了:原理的话只需要关注上面的那个 \(g\) 的合并过程,归纳一下就行。

所以每一段留 \(n+10\) 个点插值就稳过了,时间复杂度 \(O(n^3)\)\(n\) 段,\(n\) 个点值,每次求点值 \(O(n)\)

记录

22. How Many of Them

这个数据范围让我以为被诈骗到了 2333。

首先考虑割边这个东西有一个求法:找一棵 mst,对于非树边 \((u,v)\) 覆盖树上 \(u-v\) 的所有边,剩余未被覆盖的边就是所有割边。

由此我们可以看出一个图的割边不超过 \(n-1\) 条,当且仅当图是树的时候取最大值啊。

我们知道 \(n\) 点有标号连通图个数可以通过容斥简单地计算啊,事实上也有一个 egf 以后利用 exp 组合意义的做法显然没有必要。

直觉来看这个题也是类似的 dp 状物。

我们假设求 \(n\) 点大小的图答案,则 \(\lt n\) 点大小的图的答案一定是知道的。

显然双连通分量的方案数可以由连通图总数减去非双连通分量的总数,所以我们考虑割边数目大于等于 \(1\) 怎么求。

考虑如果知道了双连通分量的形态那么剩下变成了一个经典的 prufer 序列相关问题,就是说如果有 \(k\) 个连通块大小分别为 \(s_1,s_2,...,s_k\),则把他们组合起来搞成树的方案数应该是 \(n^{k-2}\times \prod_{i=1}^{k}s_i\) 啊。

如果你再枚举割边数目那么双连通分量的数目和 \(n^{k-2}\) 就是已知项了,后面的东西显然做个背包就好了。

复杂度应该是可以 \(O(n^3)\) 的但我写出了一个似乎上界 \(O(n^3\ln n)\) 的玩意不过似乎效率就是 \(O(n^3)\) 的谔谔。

记录

23. Treasure Hunt

ez 题,比赛的时候读错题白写了 1h 然后没时间做这个了。

每次等价于加入一条链,所以把每次加入的一条链缩成一个点,以链顶作为代表。

我们需要维护的是:每个链代表的对应区间(按照加入顺序排序即可),以及每个链链顶的深度。

维护这两个信息,可以做到 \(O(\log n)\) 地询问一个点所在的具体的链,以及它的具体深度。

加链的时候是挂在一条链中间的,所以考虑设一个 \(faw\) 表示挂在了链的哪个位置。

考虑最后避不开树上 k 级祖先状物,所以求距离所需要的 lca 也可以通过二分 + 树上 k 级祖先求得。

考虑怎么求树上 \(k\) 级祖先,首先跳到当前链的链顶,然后用倍增方法不断跳,每次都要跳在链顶,结合维护的 \(faw\) 就可以 \(O(\log n)\) 求得答案。

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

记录

24. Matching

首先约束等价于是钦定了子串离散化后的形态。我们考虑上 kmp。

在跳转的时候,会遇到这样一个问题(以求 nxt 为例,第二部分的匹配本质相同):

已知 \([1,j]\)\([i-j,i-1]\) 这两段离散化后同构,分别加入 \(j+1\)\(i\) 处的字符,问重新离散化后是否依旧同构。

由于两段本身同构存在良好性质,我们实质上只要判断:\([1,j]\)\(\lt S_{j+1}\) 的个数是否等于 \([i-j,i-1]\)\(S_{i}\) 的个数。

直接做,是一个在线的区间排名问题,使用主席树可以 \(O(n\log n+m\log m)\),但是常数极大,且空间不足以通过 64M 的限制。

首先 \([1,j]\) 加入 \(j+1\) 这个东西可以直接扫一遍,用一个 bit 维护,预处理出来。

由于 kmp 有一个良好性质:对于 j=nxt[j]; 这个操作我们可以改成 int p=nxt[j];while(j>p)j--; 这个步骤复杂度依然不变,原理依旧是不超过 j++ 的次数。

所以可以用一颗值域 bit 动态维护 \([i-j,i-1]\) 这个区间的情况,j=nxt[j] 跳转的时候也可以直接修改了 bit 的答案。

时间复杂度依旧是 \(O(n\log n+m\log m)\) 但是时空显然都远远优于我们最初得到的解法。

值得一提的是,本题还存在一个哈希的做法:

对排列哈希可以看作一个字符串去哈希,但我们是有一个滑动窗口在文本串上移动,然后随着你窗口的移动,离散化的结果是会变化的。

考虑令 \(p'_{p_i}=i\),也就是对逆排列哈希,这样的话只需要在权值线段树上维护哈希,插入删除单点是容易的。最后你需要把字符串的每个字符都减去一个确定的值 \(k\),这是可以做的:就是哈希值减去 \(k\times \sum_{i=0}^{n-1}base^i\)

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

记录

25. Teams

如果只有第一问,那么很简单,当我们把 \(a_i\) 排序后,有结论:连续的一段人会被划分进一组,然后可以 \(O(n)\) dp。

问题出在第二问怎么做。

考虑把 \(a_i\) 降序排序的话,比较能做:每次要么加入前面的一组,要么新开一组;可以看出升序有本质相同做法但是不太自然。

然后新开一组的时候就开到 \(a_i\),等后面往前面的组里加的时候往最小的那个里面塞就行了。

时间复杂度 \(O(n\log n)\),首先注意到这里的排序可以 \(O(n)\) 解决;然后是每次找最小的塞这个过程,可以用桶存大小为 \(sz\) 的组的编号,显然也能做到 \(O(n)\)

启示:大概是 dp 的过程中要尽可能少依赖后面,同时还要尽可能让前面的信息对后面有用?比如还有一类可以 dp 的玩意是那种球放盒子,可以选的盒子是个前缀之类的题。

记录

26. Sim

这个题,一言难尽...... 做好写 3h 还调不出来的准备吧。

考虑只有单点修改和区间数颜色怎么做,一眼带修莫队模板?显然没有前途,一个套路是维护 \(pre_i\) 表示 \(i\) 之前上一个同色段,每次就是统计 \([l,r]\)\(pre\lt l\) 的数的个数,树套树即可。

考虑一操作是什么东西:通过容斥转成求一次方,二次方,三次方和(注意到此时颜色数就是零次方和),同样要求 \(pre\lt l\),在树套树里维护。

三四操作不好做,考虑离线下来,每个数的位置就是确定的了。

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

感觉就是对标 NOIP T4 的思维巨大简单代码巨大恐怖题。

记录

27. Row Column Sums 2

首先默认行和,列和相等,否则无解。

考虑如果 \(r_i,c_i\le 1\) 那么答案就是 \(c_i\) 的阶乘。

对于等于 \(2\) 的情况考虑拆成两个行/列,但是注意到我们是可以填 \(2\) 进去的,所以首先暴力枚举填了 \(i\)\(2\),这样的话 \(r,c=2\) 的分别少掉 \(i\) 个,然后就可以大力拆行/列了:设拆了 \(cnt\) 次,显然为了去重答案应该去掉 \(2^{cnt}\)

问题在于你不能拿同一行拆出来的两行,和同一列拆出来的两列去匹配:我们考虑容斥:暴力钦定多少个这样的情况存在,这样就做到 \(O(n^2)\) 了。

当然在这题通过足够了,但还存在更优秀的解法。

这个式子可以写成 \(\sum_{i,j}A_iB_jC_{i+j}\) 的形式。

多亏 RSY 指点啊,这个东西的话,就是 \(A\times B\) 卷出来以后,和 \(C\) 的内积。

然后就在 \(O(n\log n)\) 的时间内做完了。

\(O(n^2)\) 记录

\(O(n\log n)\) 记录

28. Nice Prefixes

一个比较显然的想法是,设 \(f(i,a,b)\) 表示前 \(i\) 位确定,\(freq=\min+2\) 的有 \(a\) 个字符,\(freq=\min+1\) 的有 \(b\) 个字符的方案(隐含条件 \(0\le a+b\lt n\)),则我们可以用矩阵快速幂 \(O(k^6 \log L)\) 地转移。

不够快,考虑降低状态数,设最小值为 \(x\),则有方程组:

\[\begin{cases} a(x+2)+b(x+1)+c=len \\ a+b+c=k \end{cases} \]

第一个方程等价于 \(kx=len-(2a+b)\)

由此,我们得到:\(2a+b\equiv len(\bmod k)\)

又因为 \(2a+b\) 的上界是 \(2(k-1)\),所以 \(2a+b\) 的值只有不超过 \(2\) 种可能。

也就是说对于确定的长度来说,一共只有 \(2\times k\) 种可能的状态。

问题在于此时由于转移对于不同的长度来说是不同的,我们无法矩阵快速幂了。

发现转移的方式是模 \(k\) 循环的,所以 \(f(ik)\) 一定是 \(f((i-1)k)\) 的一个固定的线性表示,换言之你计算 \(f(0),f(k),f(2k),...,\),这个可以矩阵快速幂,最后暴力算不超过 \(k\) 轮即可。

转移矩阵的确定,就考虑枚举 \(f(0,a)\),仅把 \(f(0,a)\) 设为 \(1\),然后进行转移,最后 \(f(k,b)\) 的值,就是 \(f(0,a)\)\(f(k,b)\) 的贡献系数了。

时间复杂度 \(O(k^3\log L)\)

记录

29. Binary Representations and Queries

我是先考虑能不能从最高位开始处理,但显然不行对吧,因为可能会有一个 \(x\) 在非最高位的操作,然后再来一个 \(x\) 在最高位的操作。

然后发现 \(x\) 不同的两个操作可以随意交换,证明显然。

所以就在 \(O(n\times 2^n+q)\) 的时间内解决了。

记录

30. GRE Words Once More!

模拟把这个题进行了加强:\(k\le 10^18\) 且不保证图是 dag。

首先我们思考 dag 上怎么做:显然,我们把每个点的边按照上面的字符排序,然后设 \(f(u)\) 是点 \(u\) 出发得到的单词数,则我们可以得到一个单次 \(O(n)\) 的解法。

然后有一个这样的东西:设 \(u\) 的所有儿子里 \(f\) 最大的是重儿子,进行链剖分,这样轻边最多走 \(O(\log k)\) 条,对于重链,倍增求出 \(k\) 的上下界即可。

然后我们容易发现非 dag 上一样能做,只要把无穷多种方案的 \(f\) 视为 \(\infty\) 即可。

注意到显然有上界 \(10^5\times 10^{18}\),狂暴 define ll __int128 好像速度比我想的要快...

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

记录

31. Keep Being Substring

应该是比较简单的 ARC E?

首先头尾操作的话就要想到任意时刻保留的一定是个区间,这是个比较套路的东西。

如果在最后,\(p\) 中的 \([l,r]\) 段被保留,意味着 \(q\) 中,这一段也出现了。

然后发现,显然我们可以得到一个答案:\(|p|+|q|-2|s|\),其中 \(s\) 是两者的最长公共子串长度。

问题在于两者没有公共子串的时候,换言之就是连字符集都没有交。

首先你肯定要把 \(p\) 的字符全删空,要把 \(q\) 的字符全加上,这就天然带 \(|p|+|q|\) 的贡献:然后考虑其它字符,只要你添加了,就必然删除,带来 \(2\) 的贡献,我们要最小化添加的无用字符。

如果在一个串 \(S\) 前(后)添加一个字符合法,只要 \(|S|\ge 2\) 一定能删掉 \(S\) 的头/尾使得添加该字符依旧合法。

所以我们考虑初始的时候把 \(p\) 的字符统统删掉只留下一个字符,这样自由度最高。然后每次添加一个字符,就把原先那个字符删掉,你的目标是当前你拥有的字符属于 \(q\) 的字符集。

发现这相当于一个多源最短路问题:把值看作点,连 \((A_i,A_{i+1})\) 这样 \(n-1\) 条边即可。

算上哈希求 LCS,时间复杂度 \(O(n\log^2 n)\),不难发现理论上线性构建 SA 可以做到 \(O(n)\)

记录

32. Distance to the Path

考虑一条路径 \((u,v)\) 修改的贡献,显然,我们会分成两部分考虑:影响 \(lca\) 所在的子树,以及子树以外的点。

先考虑子树内的点,如果只有一个点那么ez,问题在于多个点啊:不妨让被影响的点向上走,只要向上走 \(d\) 步以内能到达路径上,就会被贡献到,我们希望让他第一次走到路径的时候算贡献,后续往上爬不在计算贡献。

考虑设 \(f(u,d)\)\(u\rightarrow fa_u\) 攀爬且算上之前已经攀爬了 \(k\) 步的答案。我们每次修改路径会对一个类似毛毛虫的结构的 \(f\) 加上 \(k\),这样做是不好做的,但是考虑被修改的点的父亲全部并在一起就是路径 \(u\leftrightarrow v\),所以我们打两层 tag:一个打在父亲上,一个打在儿子上,这样的话就可以了。

然后发现 lca 子树外的贡献方式统计是一样的。

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

记录

33. The Beach

场上没有把模型想的很清楚,导致最后卡了半天如何处理一个空格同时贡献给两个位置的情况,赛后发现不可能出现......

首先想到枚举那个 \(1\times 2\) 的位置,然后相当于你要找两个空格挪到这个位置。

分析一下发现似乎每个椅子不会挪动超过一次:除非你用两次旋转代替一次平移,我们暂且记下这种情况。

我们的目的就是把空格移到我们指定的位置上:观察移动方式:注意到可以把图黑白染色,则空格的颜色是不变的。

然后我们就直接考虑这样建图,跑最短路即可。

但为什么是对的?比如上面说的,两次旋转代替一次平移,这个直接建图似乎并不能考虑到。

我们会发现,其实只用一次旋转就够了,所以“每个椅子不会挪动超过一次”是真的结论,因此建图就是对的。

另外,我们会发现这样做,显然不会出现一个空格同时贡献给两个位置的情况,因为我们是黑白染色的。

最后,虽然两条路径没有交,但他们会不会经过一个相同的床?不妨设两条路径都想让床旋转,则至少多出两个额外空格;我们只需要把床往一边旋转,则旋转腾出的一个空格,以及原先多出的一个额外空格直接就组成了一个 \(1\times 2\) 的空格。对于“一条路径让床平移,另一条路径让床旋转”,以及“两条路径都想让床平移”的情况,可以类似地分析。

所以我们就说明了这样建图的正确性,时间复杂度 \(O(nm\log (nm))\)

记录

34. N Machines

应该是第一次完全独立想出 3300* 啊,而且我觉得这个 E 并不比上面的 D 难想。

\(\omega = 2\times 10^9\)

首先忽略 \(\times 1\) 这样的操作,我们注意到:乘法操作不超过 \(\log_2 \omega\) 个。

另一方面,如果我们动乘法,一定让它动到最后面;如果我们动加法,一定让它动到最前面。

注意到乘法个数很少,所以我们有一个想法:先确定把哪些乘法放到了最后面,此时我们会有一个 \(cnt\),意味着我们最多还能把 \(cnt\) 个加法提前,我们想知道此时最优秀的答案。

考虑设有 \(x\) 个乘法,则把所有加法划分成了 \(x+1\) 段。首先我们知道,一个 \(+a\) 的操作提前,对答案的新的贡献肯定是个 \(+a\times d\) 的东西,我们发现在同一段里的加法操作,你把他提前,\(d\) 一定是相同的。

显然我们会把 \(d\times a\) 最大的 \(cnt\) 个数提前,这引导出一个 \(O(n\log n)\) 的做法,但考虑到 \(n\) 本身就是 \(10^6\) 了,那么我们还有第一部分处理乘法的情况没有做,显然是难以通过的。

由于本质不同的 \(d\) 只有 \(x+1\) 个,而每一段内我们比较 \(d\times a\) 就是比较 \(a\),所以我们把每一段的加法操作按照 \(a\) 降序排序:注意到此时是一个类似 \(x+1\) 个段归并的过程,每一段选取的一定是个前缀:我们直接枚举每一段,然后二分最后一个被选中的位置即可。

总而言之,这可以在 \(O(\log^2 n \times \log \omega)\) 的复杂度内解决,显然 \(20\times 20\times 30=1.2\times 10^4\) 远比 \(10^6\) 优秀。

现在考虑第一部分,乘法的安排。一个显然的上界是 \(2^{\omega}\),但我们思考一下 \(30\) 个乘法操作都是 \(\times 2\) 的情况就会发现一个事实:对于若干个 \(d\) 相同的 \(\times d\) 操作,我们一定会先去把位置靠前的乘法提到最后。

所以我们只需要爆搜每个 \(d\) 提前了多少个即可,显然这个方案数不会很大,就可以通过了。

记录

35. 命运

考虑 dp:设 \(f(u,i)\) 表示 \(u\) 子树边已经确定,要求 \(u\)\(u\)\(i\) 级祖先必须有一条边为 \(1\) 的方案数。

这个 dp 可以做,但我们发现复杂度很大。

注意到对于每个 \(v\) 来说,只关注深度最大的和它约束的祖先 \(u\),设 \(f(u,v)\) 表示 \(u\) 子树边已经确定,要求 \(u\rightarrow lim_v\) 的边上必须有一条边为 \(1\) 的方案数。这样 dp 的优点是,你把第二维成功和 sz 绑定了起来:而当我们的一维和 sz/depth 可以绑定起来后,就有优化的出路了。

转移是一个这样的卷积:\(f(i)g(j) \rightarrow h( \max\{i,j\} )\)

由上面的两条性质,可以用 seg 合并来解决,不过当 if(!x || !y)return x+y 出现的时候,操作实质是区间乘法,所以这个线段树还要支持 pushdown。

值得一提的是,带区间加法动态开点我们会发现好像会多开很多的点(由于pushdown),但如果假设序列初始为 \(0\),那么带区间乘法动态开点的线段树不会多出任何的空间需求啊。

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

记录

36. Fishermen

最近越来越感觉,很多你给不出精细构造方案,或者乍一看不太能多项式复杂度的题目,都可以先尝试一下建立网络流模型。

固然重排以后 \(b\) 数组是容易确定的,然而,我们并不能对这个排序分析出什么东西,可能会想说:exchange argument,然而我们并没有什么实质性的结论出现。

所以考虑能不能绕开排序的限制,或者说构建一个看上去静态一点的模型。

我们发现实质上就是每个数取一个倍数,让他们互不相同。

而且我们会发现最多取到 \(n\) 倍,因为显然不可能 \(1\)\(\sim\) \(n\) 倍都被其他人占据了。

那么就可以建立一个带权二分图的最小完美匹配,边点都是 \(n^2\) 的,至少有点出路。

发现这张二分图有两个性质:第一,左部点很少;第二,对于所有右部点,到它的权值是相等的。

此时我们首先可以把左右部互换,把左部点排序以后直接跑匈牙利,道理大概是基于匈牙利的一个“无后效性”就是说我们加入一个点会尝试改动其它点的匹配,但是最大匹配数目一定不会变,而且取出的左部点集合不变。

这样的话还没有利用一个部分的点很少这个性质,而且是 \(O(n^4)\) 的,最后一步优化可能是个算 trick 的东西,它当然也适用于一般的匈牙利,就是如果我们只在匹配的时候才清空 vis 数组那么复杂度会变成 \(O(\min\{L,R\}\times m)\) 这个级别,复杂度是这样分析的:最多 \(\min\{L,R\}\) 条匹配边,相邻两条匹配边的确定,最多把所有边各遍历一次;正确性是这样体现的:vis 的本质是让一个点尝试退掉已经有的匹配边,而如果你的匹配没有发生变化,之前不行,现在一定也不行。

不过这个优化在 \(L,R\) 同阶的时候显然用处并不很显著。

时间复杂度 \(O(n^3)\)

记录

37. 航空管制

很趣味的题,目前网上似乎清一色都是建反图的题解,然而我觉得这个想法既不自然更不必要,还没有体会到其精髓在哪里。

考虑若 \(u\rightarrow v\) 则我们实质上可以认为 \(k_u\lt k_v\),然后按照 \(k\) 升序排序就做完了第一问。

容易发现按照 \(k\) 升序排序也是最优秀的一种方案。考虑第二问怎么做,我们枚举 \(i\) 并计算答案:首先把可以走到 \(i\) 的点都拿出来,他们应该也是按照 \(k\) 排序的;剩下的点放到 \(i\) 之后,同样按照 \(k\) 排序。

问题在于剩下的点中可能已经有不合法的了,首先观察到如果一个点已经不合法则它必然要提前,提前以后的方案我们不用考虑,因为肯定也是和 \(i\) 及以前的点升序混在一起。若 \(x\lt y\)\(y\) 被提前说明 \(x\) 的位置将被延后,因此我们此时考虑倒着遍历数组 \(a\)\(a\) 是走不到 \(i\) 的点按照 \(k\) 升序排序的结果),只要碰到不合法的,就往前塞。

最后,往前塞的总数,加上初始在 \(i\) 之前的个数,加上 \(1\),就是 \(i\) 的最小 rk。

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

记录

38. Ternary String Counting

质量很高的 dp 题啊。

考虑暴力一点的 dp 想法:不难想到设 \(f(i,j,k,l)\) 表示前 \(i\) 个位置确定,且右端点 \(\le i\) 的区间一定合法,三种颜色的最近一次出现分别是 \(j,k,l\) 的方案数。

我们发现,\(j,k,l\) 必定有一个是 \(i\),所以可以砍掉一维变成 \(f(i,j,k)\) 并且我们可以假设 \(j\ge k\)

思考转移,忽略合法性,我们有三种转移目标:\(f(i+1,j,k) / f(i+1,i,j) / f(i+1,i,k)\)

我们发现这个转移很有特色:第一类转移实际上是第二维第三维没动;第二类转移,第二维一定是 \(i\),所以就思考如何优化这个转移。

我们任何时刻仅保留第二维和第三维,这样转移的时候,不做任何变动,就相当于完成了 \(f(i,j,k)\rightarrow f(i+1,j,k)\) 这件事。

考虑如何处理后两种转移,只需要时刻维护:\(b_j\) 表示所有 \(f(i,j,k)\) 的和,以及 \(c_j\) 表示所有 \(f(i,k,j)\) 的和,那么 \(f(i+1,i,k)\) 就应该是 \(b_k+c_k\)

而且我们发现单次修改一个位置的 dp 值,\(b,c\) 都是容易 \(O(1)\) 维护的。

现在回到合法性的问题上来:就是说,他在任何时刻钦定了我们只能保留 \(j\) 在一个 \([L_1,R_1]\)\(k\) 在一个 \([L_2,R_2]\) 范围内的 dp 结果,其它的全部删除。

首先容易想到对于每一个第二维 \(j\),维护一个 set 表示多少个 \(dp(j,k)\) 是存在的,这样就可以做到 \(O(n^2\log n)\) 了,但是依旧有点不够优秀。

注意到任何时刻,对于一个 \(j\),其 set 里的值显然构成一段区间,我们只需要用两个变量维护即可。时间复杂度 \(O(n^2)\)

记录

39. Walk

由于模拟似乎是从别的地方偷了这道题,我至今不知道原题地址。

简略题意:给出一颗树,树根为 \(1\),带点权 \(a_i\)。保证所有点权都是 \(a_1\) 的约数。

\(x\) 可以跳到 \(y\)\(x\neq y\))当且仅当:

  • \(x\)\(y\) 的祖先。

  • \(a_y\mid a_x\)

对于每个点 \(u\),求 \(1\) 跳到 \(u\) 的方案数模 \(10^9+7\) 的值。

\(n\le 10^5,a_i\le 10^{18}\)


显然最直观的想法是在 dfs 过程中维护这样一个动态的东西:维护一个值域是 \(10^{18}\)\(b\) 数组,有两种操作:

  • 修改:\(b_x:=b_x+v\)

  • 查询:\(\sum_{x\mid y}b_y\)

显然查询是这个问题的难点。

我们知道至少存在一些做法(例如 pollard-rho)可以预先分解出所有点权的质因子,所以我们假定把每个数分成了质因子的形式。

发现这实际上是一个动态高维前缀和,似乎难以在 polylog 内实现。

显然最后可能的坐标不超过 \(10^6\) 级别个(\(10^{18}\) 内约数最多的数的个数),不妨令 \(d=10^6\)

我们可以做到近似的把 \(\omega\) 个维度分成两个不会超过 \(\sqrt{d}\) 太多的部分,然后就是常规的分块了。

忽略分解质因数的部分,则时间复杂度约为 \(O(n\sqrt{d})\),一些计算坐标的部分可能需要多乘上一个 \(\omega\),但实际上其效率很高。

而关于分解质因数,也存在一个不用 pollard-rho 的 \(O(a_1^{\frac{1}{3}})\) 的做法(需要注意的是这个做法并不是确定的,他不能分解出所有质因数,但有时候我们并不需要所有质因数)。

其思想就是如果我们只排除掉了不超过立方根级别的质因子,那么剩下的只可能是 \(4\) 种情况:\(1,p,p^2,pq\)

把不超过立方根的质因子集合记作 \(S\)。如果留下一个 \(1\),那么分完了;否则,我们用 \(S\) 分解 \(a_{2\sim n}\),如果留下的都和分解 \(a_1\) 是一样的,那么我们可以把留下的视作一个质因子,否则不管是 \(p^2\) 还是 \(pq\),你都知道了其中一个数的值,就能知道另一个质数的值。

记录

40. Brackets(Problem A)

大体想法:找到最小的 \(x\),满足 \([1,x)\) 确定,且 \([x,2n]\) 是字典序最大的合法排布方式,然后调整 \(x-1\) 处的值,并让新的 \([x,2n]\) 最小化。

第一步是比较恶心的,大致是考虑我们还没有完成匹配的若干个左括号,由于原串合法,所以右边一定按顺序有对应的相同个数的右括号匹配,这部分必须保留,其它的我们暂且删去。

考虑什么时候 \([x,2n]\) 取到字典序最大的合法排布方式,找到最大的左括号,根据其与对应的右括号关系,我们最后可能会插入形如 (((...))) 或者 ()()...() 这两种形式的括号串。

只需要从我们保留的那些右括号中,找到最靠前的一个右括号,满足其字典序先于最大的左括号,在这个位置前插入我们的括号串即可,所以我们可以算出在哪个位置插入,然后哈希判断(我降智写了 st 表)一下即可,至于找到位置,由于最大的左括号是个确定的东西,所以用 set 即可维护(我再次降智写了 seg)。

不难发现最后第三部分重构的思想是类似的,时间复杂度 \(O(n\log n)\),第二部分的判断也是容易的。

感觉最多写个 3k 就差不多了,我写了很多 DS 所以接近了 6k......

记录

posted on 2022-10-01 15:21  Cry_For_theMoon  阅读(225)  评论(3编辑  收藏  举报