UOJ Logo rushcheyo的博客

博客

UOJ Round #21 题解

2021-05-29 23:10:16 By rushcheyo

士兵调度

from zx2003

子任务一

构造方法非常多。

一个简单的办法是,对于所有 n 名士兵,将第 i 个士兵的坐标设为 (i,i)。然后对于所有 m=n1 次移动,第 i 次移动将第 i+1 个士兵挪到第 1 行。容易发现这样总的变化次数恰好为 n

子任务二

构造方法仍然非常多。这里给出一种常数较优的做法。

取一个 400×500 的棋盘,将其黑白染色,并在所有黑格上放上士兵。之后每次操作将相邻列的士兵合并起来,这样所有 n 个士兵所属的分组都会变化恰好一次,并且操作步数只需 250

子任务三,四

我们分析下这个问题的性质。

对于一组 y 坐标相同的士兵,设其中有 a 人分组为第二组。则按照分组规则,这些士兵所属的 x 坐标上一定分别有不少于 a 名士兵。故而,a 一定不超过 n。对于 x 坐标进行同样分析,我们就知道了每次操作后分组变化次数一定不超过 2n

对于总的操作次数,我们可以得到一个更好的上界。注意到每次操作时合并的两行中,较小的那一行贡献的变化次数可以用启发式合并的来分析,这一部分的步数总和是 nlogn。所以总的变化次数的界为 mn+nlogn+O(n+m)

下面给出标算的构造。

我们将操作分为若干轮执行。对于第 T 轮,我们需要将点集由 (T1)×(T1) 的正方形增加一行一列变为 T×T 的正方形,这样在该轮中所有 (T1)×(T1) 个原正方形中的点的分组都会变化一次。我们可以现在平面远处预先放好点,用到时再移过来即可。注意由于两维坐标的不对称性,实现时需要注意增加行和增加列的先后顺序。

这样的操作不一定能恰好契合 n,m 的大小,我们截取按照这种构造方法生成的前 n 个点,再将前 nm 个点在所有操作开始前就摆在它最后应在的位置上。

最后总的操作步数大约为 i=nm+1ni,遗憾的是未能贴紧理论上限。

题外话

本题是来自于 UOJ #309,那道题需要维护每个点的偏好维度。当时一些提交代码是用 vector 存储每行每列上的关键点。按照前面分析这只有根号个,但是众所周知 vector 的动态操作常数很大,所以我当时就想卡下 vector 动态操作的常数。但最后 vector 莫名其妙跑得飞块,我怀疑是因为构造涉及到的点的坐标本质上只有 O(n) 个,然后缓存非常友好。当时尝试 hack 是失败了,不过也有了现在这道题。

不下发 OJ 上的 O(mn) checker 是因为 checker 的实现可能会对选手做题产生提示作用。

挑战最大团

from JohnVictor

算法一

我会堆暴力!期望得分 40 分。

算法二

首先注意到一个性质,就是优美的图和它的补图不能同时连通。

证明:对 n 归纳,设这张图为 G,顶点集为 V

如果 n1 时成立,注意到优美的图的子图和补图仍然是优美的,我们反证,假设原图和补图都连通。

任意找出一个节点 v,如果它和所有的其余节点都连边,那么补图不连通,因此我们不妨假设 v 在原图和补图中都有边。

我们考虑 Vv 的原图 G1 和补图 G2,由归纳假设它们不同时连通。

不妨假设 G1 不连通,否则我们考虑 G 的补图也是一样的。假设 G1 的连通分支为 X1,X2,,xt(t2),由于 v 不向所有点连边,所以一定存在一个连通分支,不妨设其为 X1,使得 v 不向 X1 中的所有点连边。

SX1 中和 v 连边的点构成的集合,T 为与 v 不连边的点构成的集合,X1 的连通性表明存在 aS,bT 使得 a,b 连边。再由原图的连通性存在 wX2 使得 v,w 连边,此时 batv 构成诱导 P4,矛盾。

那么我们可以考虑递归求解这个问题,考虑答案的生成函数,如果原图不连通那么 GF 就是连通分支的 GF 相加,如果补图不连通那么一个顶点集构成团当且仅当它在补图的每一个连通分支中都构成团,也就代表这个 GF 是连通分支的 GF 相乘。

暴力 BFS 判断连通性,时间复杂度 O(n3),期望得分 60

算法三

使用 std::bitset 优化上述暴力 BFS 即可,因为这个图如果连通那么补图不连通,也就是直径为 2,可以扩展出第一层节点之后使用或操作。时间复杂度 O(n3/w),常数很小,期望得分 70

算法四

我们考虑更快的找出连通块。使用启发式分裂的思想,我们希望如果一次 BFS 将图分为大小为 x,y 的两个部分,使用的代价为 O(xy)

仍然应用直径为 2 的性质,首先在原图和补图中各取一个度数最小的节点,然后扩展第一层节点,之后再进行并行 BFS,也就是原图和补图依次扩展一个节点,直到确认其中一个连通为止(显然原图和补图至少有一个连通),可以证明复杂度是 O(n2),期望得分 100

补充一句,复杂度满足要求是因为设最小度为 x,那么较小的一部分大小至少为 x+1,而扩展的代价至多为 x(x+y)2xy

算法五

from djq_cpp

注意到上述算法的本质是用一棵树来刻画这个图,具体地,一个这样的图能和一棵 n 个叶子的树一一对应,两个节点连边当且仅当 LCA 为奇数。

现在我们考虑建树,只用 O(n) 在前 n1 个点的树中插入一个节点即可。

可以证明在插入一个节点之后,这棵树只有一条链上的节点会发生变化,因为如果互不包含的两个子树中都有向新节点连边的,容易找到一条 P4,补图也一样。

现在我们只用找出这条链,具体做法是 DFS 并维护出哪些点的子树到这个新节点连边情况完全相同(全连边或者全不连边),找出不同的这一条链之后,再专门去改变这条链的节点即可,具体可以见这份代码

时间复杂度 O(n2),常数略大于算法四,期望得分 100

你将如闪电般归来

from deadecho

EntropyIncreaser 氏加强!!!

为了叙述方便,接下来叙述的 k 是原题面中输入的 k 减去 1

算法一

考虑按照题意自底向上进行 DP。设 fk,nk 层,n 个节点对应的答案。那么有 f0,n=[n=1] 和递推式 fk,n=m=0n1(n1m)fk1,m[n1m0(mod2)] 时间复杂度 Θ(kn2),期望得分 1525

算法二

算法一中的递推式可以写作卷积,因此可以用 FFT 优化,时间复杂度 Θ(knlogn),期望得分 25

算法三

考虑将问题写作生成函数,设 Fk(x)=nfk,nxnn!,发现有关系 F0(x)=xFk(x)=0xFk1(u)eu+eu2du 我们发现直接积分是没有显式表达式的,但考虑建立辅助生成函数 Fk(x)=Gk(eueu2)

接下来我们记 coshx=ex+ex2,sinhx=exex2。但我们接下来不会用到任何双曲三角函数结论。 Fk(x)=0xGk1(sinhu)coshudu=0xGk1(sinhu)d(sinhu)=0sinhxGk1(t)dtGk(x)=0xGk1(t)dt 而我们的目的就是算出 [xn]Fk(x),因此我们可以分为计算 Gk(x) 的前 n 项系数和所有的 [xn](sinhx)m,mn

G0(exex2)=x,根据复合逆关系,设 u=G0,那么 eueu2=x,设 t=eu,也就有 t1/t2=x,解得 t=x+1+x2,也就有 G0(x)=sinh1x=ln(x+1+x2)

Gk(x) 是将 G0(x) 连续积分 k 次,也就有 [xn]Gk(x)=1nk[xnk]G0(x),预处理阶乘就可以做到 Θ(n) 计算 Gk(x) 的系数。

而根据 Lagrange 反演公式,有 [xn](sinhx)m=mn[xnm](xsinh1x)n

综上,我们可以通过计算生成函数的幂在 Θ(nlogn)Θ(nlog2n) 内完成。预计得分 40

算法四

n 很大的时候,我们不得不考虑 Fk 的具体形式。

我们考虑二元 GF F(x,t)=kFk(x)tk,可依 Fk 的递推关系列出方程 F(x,t)=x+t0xF(u,t)coshuduxF=1+tFcoshx 根据一阶 ODE 的通解形式,确定常数项之后我们得到了 F(x,t)=etsinhx0xetsinhudu 提取 [tk],可知 (1)Fk(x)=j=0k(sinhx)kj(kj)!0x(sinhu)jj!du 注意到有积分 0xejudu={ejx1jj0xj=0 可知 Fk 的形式为 xaecx 的线性组合,其中 0a1,kck

可以使用上述和式,通过 FFT 在 Θ(k2logk) 时间内计算出 xaecx 基下的系数,如果暴力按照积分式递推系数则可做到 Θ(k2)。预计得分 60,和算法三拼起来可以获得 75

算法五

我们希望加速 xaecx 基的系数的计算,考虑 Fk(lnx)=Gk(x1/x2) 是一组 xc(lnx)a 基,为了借助微分方程的力量,我们首先考虑 Gk(x) 的微分性质。

A(x)=(sinh1x)=(1+x2)1/2,记其系数为 an。那么有递推式 nan=(1n)an2bn=ank1nk+1,即对应的 B(x)=Gk(x)A(x)k+1 次积分,可得递推式 (nk1)ank1=(2n+k)ank3(nk1)bnnk+1=(2n+k)bn2(n2)k+1n(n1)(nk1)bn=(nk1)(nk2)2bn2(nk1)(n(n1)bn+(nk2)2bn2)=0n(n1)bn+(nk2)2bn2=1(k1)![n=k+1]k2x2B(x)+(12k)x3B(x)+x2(1+x2)B(x)=xk+1(k1)!k2B(x)+(12k)xB(x)+(1+x2)B(x)=xk1(k1)! 我们考虑设 X=x1/x2,令 P(x)=B(x1/x2),考虑列出 P,B 之间的导数关系。 P(x)=(1+x22)B(X)P(x)=(1+x22)2B(X)x3B(X)B(X)=(21+x2)P(x)B(X)=(21+x2)2P(x)+x3(21+x2)3P(x) 这就导出了 P(x) 满足的方程 k2B(X)+(12k)XB(X)+(1+X2)B(X)=Xk1(k1)!k2P(x)+(12k)X(21+x2)P(x)+(1+X2)[(21+x2)2P(x)+x3(21+x2)3P(x)]=Xk1(k1)!k2(1+x22)3P(x)+(12k)X(1+x22)2P(x)+(1+X2)[(1+x22)P(x)+x3P(x)]=Xk1(k1)!(1+x22)3k2(1+x2)P(x)+((1+2k)x+(12k)x3)P(x)+(x2+x4)P(x)=Xk1(k1)!(1+x2) 由此我们已经得到了 P(x) 满足的一个微分方程,将其提取 [xnlnx] 设为 gn,提取等式两边的 [xnlnx] 可得递推式 (n+k)2gn+(n2k)2gn2=0 再提取 [xn] 设为 fn,提取等式两边的 [xn] 可得递推式 (n+k)2fn+(n2k)2fn2+2(n+k)gn+2(nk2)gn2=[xn]Xk1(k1)!(1+x2)

还需解决边界值问题,根据 (1) 式可知: fk=12kj=1k(1)j(kj)!j!j=12kk!Hkgk=12kk! 由此即可从大到小递推,在 Θ(k) 时间内计算出系数,然后通过线性筛,只需计算 π(k)klnk 次快速幂,时间复杂度 Θ(klogkmin(n,p))。预计得分 100

后记

在操作过程中,我们考虑了复合 B(x1/x2),但 B 是形式幂级数,复合的 x1/x2 既有正次项又有负次项,其即使拓展到 Laurent 级数也无法定义复合,但我们对微分方程的推导得到的,对于 xc(lnx)a 组成的「生成函数」给出的系数递推式也确实给出了正确的答案。如何更加严格刻画这种推导,或许是个有趣的问题。

评论

有处笔误,对于一族 y 坐标相同的士兵,应该是对于一组 y 坐标相同的士兵
前排
[我的做法](https://uoj.ac/submission/478491),其实和 DJQ 的差不多:任取节点 u,先将其余节点分为相邻点 X=N(u)Y=N(u){u} 两部分。又考虑任取节点 xX,yY,检查是否有 (x,y)G。这里相当于 u 在最终的树结构到根的一条链,将剩余子树分割为了若干部分,如果 (x,y)G,说明 LCA(x,u)LCA(y,u) 深度更小,反之 (x,y)G 则更大。由此我们可以简单地按照 X,Y 之间的度数对两边进行基数排序,其中度数相同的在一个子树中递归。最后判一下离 u 最近的点在 X 还是在 Y,自底向上交替合并。 单层复杂度是 Θ(|X||Y|) 显然满足树上背包。而且对任意图来说这个过程都是严格的 Θ(n2),容易改成 validator。

发表评论

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