UOJ Logo zhoukangyang的博客

博客

UOJ Round #29 题解

2025-02-17 11:51:29 By zhoukangyang

随机浏览

idea by GeZhiyuan, solution by GeZhiyuan, shr, std by shr, data by GeZhiyuan

算法 I

考虑必定是存在一些页面,如果到达了这些页面,就回到页面 1。可以直接枚举会回到 1 的页面集合 S,然后暴力进行高斯消元,复杂度 O(2n×n3),预计通过 12 分。

算法 II

考虑假设 m 轮后,即使没有到达 n 也不会继续操作,只要 m 取到足够大误差就可以接受,复杂度 O(m×n2)。预计通过 48 分。

通过精细卡常可能能通过 72 分。

算法 III

考虑先强制让所有页面都不会按红色按钮,然后记 fi 表示目前在页面 i,要到页面 n 期望要随机选择几次。每次找出最大的 fi,如果最大的 fi 不为 f1,则令到达这个页面后会点击红色按钮回到 f1,每次消元复杂度 O(n3),又至多只会 n 次让页面点击红色按钮,因此复杂度 O(n4)。预计通过 72 分。

算法 IV

考虑利用动态高斯消元优化 算法 III,复杂度 O(n3)。预计通过 100 分。

动态高斯消元的方法可以参考 [集训队互测2015] 最大异或和 的题解。

数字生命

idea by dead_X, solution, std by zhoukangyang, data by zhoukangyang, Rainbow_sjy

小故事

这题是三年前 dead_X 看错一道题后给我报的题意。听完题后我很快就想出了做法!而且感觉这个做法很趣味!之前没怎么见到过这种思路!

后来又在其他题/博客里面发现了这类做法,感觉有点错!但查询了一些选手的看法,他们认为即使见过这些也不简单!

WC2025 中我自己又讲了相关的内容,就当是抹平技术差距了(雾)

算法一

首先,我们差分 a 序列,设差分结果为 c

一次操作就是将 c 的第 p 个位置 1(需要保证 cp1),将 c 的第 p+len 个位置 +1

此时我们可以将问题看成是,第 i 个位置有 cici 可以为负) 个石子。每次我们可以将一个石子向前移动 len 步,最终我们要让每个位置的石子数清零。我们可以把这里的 "正 ci" 看成一个石子移动的起点,一个 "负 ci" 看成一个石子移动的终点。

容易发现,起点个数等于终点个数,且如果想要有解,则最多只会有 m 个起点。

根据这个转化,我们可以写出 DP:从往后加入起点,记录此时已经匹配的终点和使用的操作。维护这个 DP 大约要 O(4m) 的复杂度。

根据算法的复杂度和减枝程度,可以获得 3075 分。

算法二

Gi,j 表示从第 i 个起点走到第 j 个终点,可以使用哪些操作集合来进行操作。我们给每个 "操作集合" 随机赋值,并将其看成一个集合幂级数。

而我们想要求的是 piGi,pi,其中集合幂级数的乘法是子集卷积。

注意到我们其实并不关心每个排列带的系数是什么,所以我们要求的也可以是 psgn(p)iGi,pi

这就是一个对集合幂级数求 det 的问题了。但是如果使用子集卷积,复杂度带的 m 因子会过多。

我们发现我们可以直接使用或卷积。因为如果或卷积中有重的元素了,那么我们使用的操作的子集和一定和原序列的总和对不上,因此只需再对总和做限制即可。

算答案的每个点值需要 O(m3) 的复杂度,总复杂度 O(2mm3)

人机验证

idea by xyf007, data, std by zhoukangyang, solution by zhoukangyang, EntropyIncreaser

小故事

这是 NOI2023 后的暑假时给出的做法。

当时 xyf007 找我问这个题。我看了一下发现就是求带深度限制的有根树计数,然后思考了一下,发现有些困难。感觉这是典题,所以咨询了 EI,EI 告诉我他也很好奇这题能不能做。

xyf007 告诉我这题能做,而且我之前说出过正确做法。我隐约感觉有些印象,就又开始思考这个问题。断断续续想了几天,我终于想出了一个低于平方的做法!而这题之前的做法并不正确。我把这个做法告诉了 EI,EI 提出用特征多项式优化的做法,能做到 O(nnlogn)

近几天准备这道题的时候,我重新思考了一下这个问题,发现有了快速的多项式复合后又有另一种 O(nnlogn) 做法,以及【数据删除】。

题解

显然,问题的难点在于求 n 个点深度不超过 k 的有标号有根树个数。

首先容斥,钦定一些元素的深度恰好为 k+1,然后把这些点和他们的祖先都标记了(即保留”虚树“上的点)。

真实的树就是在每个”虚树“上的点上长出一颗新的树,所以答案只和虚树上的点数有关。

可以据此写出一个看起来没啥变化的 DP 来统计虚树上的点数:

F0=x

Fi=x(exp(Fi1)1)

求出 Fk 即可得到答案。

接下来我们考虑另一种 DP:

dpd,r(x),其中 [xc] 表示离叶子高度为 d 的恰好有 r 个点,且总点数恰好为 c 的方案数。其中,有 rnd

dpi1dpi 的转移系数是个第二类斯特林数。我们要求的是 dpk+1

注意到 dpd,r=Fdrr!。所以我们可以定一个阈值 B,用第一种 DP 算出 dpB

此时考虑如何用 dpB 获得 dp2B。这里设 m=nB

注意到第二维大小不大,因此可以考虑矩阵快速幂。如果直接使用矩阵快速幂,需要对一个 len 维护 m×m 的矩阵 G,其中 [xc]Gi,j 表示第 0 层有 i 个点,第 len 层有 j 个点,总共有 c 个点的有标号有根树个数。

接下来有两种做法。

做法1

把整个矩阵记下来很浪费。考虑设 Hi(x)=jGi,jyj,可以发现 Hi=H1i。因此只需记录 H1

接下来考虑如何"翻倍",即 lenlen×2。这无非计算 i[yi]HiHi,对 x 这一维插值,对 y 这一维就是多项式复合。

使用 2log 的多项式复合,我们可以做到 O(m2lenlog2n) 计算长度为 len 的转移矩阵。而对于一个多项式 Fx,我们通过其计算 Fx+len 可以做到 O(nm)

因此复杂度是 O(Blen×nm+m2lenlog2n)=O(n2len+m2lenlog2n)。取 len=nmlogn 即可得到 O(nmlogn) 的复杂度。

B 最初取 n,总复杂度 O(nnlogn)

做法2

这个转移矩阵是对角矩阵,有特征多项式 f(y)=i=1m(yxi)

由于 Fi=dpi,1,序列 Fi 有线性递推 f。我们计算出 FB,FB+1,FB+2,...,FB+m,然后只要计算出 yBmodf(y) 即可知道如何用 FB,FB+1,...,FB+m 线性表示出 F2B

考虑倍增计算 yBmodf(y)。注意到 ykmodf(y)x 上的多项式次数是 O(km) 的,总大小是 O(km2),因此需要的复杂度是 iB2im2logn=O(n2Blogn)。你也可以通过对对 x 这一维插值、对 y 这一维取模来计算这个式子。

B 最初取 O(n),总复杂度 O(nnlogn)

评论

有人有T1题解吗/kk
评论回复
Euler_function:https://www.luogu.com.cn/article/w942xq6r
Euler_function:可能写的不是很详尽,大概能看就好,有问题可以私信我。
Euler_function:抱歉,我太菜写了个假做法,代码被 sjy 卡了,等我修掉/ll
Euler_function:修正:查证是被 tiansuohaoer 老师卡了,现在改了一下至少能过
催更 T1 题解。
T1 的 std 是不是锅了,,,
评论回复
Rainbow_sjy:昨晚已修复(
T1“每次取出最大的f_i”,有非常严谨的证明吗
T1如何证明只用n次
评论回复
masterhuang:改成回 1 后不会再改成 不回 了,所以只用 n 次
动态高斯消元是什么姿势
T1 的正确性证明呢?
T1 动态高斯消元真的不用离线吗,但每次修改fi最大的应该必须在线解决吧
zak能完整地背出圆周率——是倒着背。 zak口渴时会用巴拿赫-塔斯基悖论弄出更多橙汁。 zak不能理解随机过程,因为他能预测随机数。 询问zak一个命题是真的还是假的,构成了一个严格的证明。 有一次zak证明了一条公理,但他不喜欢它,所以他又证明了它是假命题。

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。