【比赛题解】NOIP2020 题解

 


T1. 排水系统

LOJ #3386

Solution

将每个 " 排水节点 " 看成是一个 " 点 ",将每个 " 单向排水管道 " 看成是一条 " 单向边 "。

不难发现,得到的图是一张 DAG。

直接模拟题意即可。依次松弛每个节点的蓄水量,直至到达最终排水口。需要注意的是,在松弛任意一个节点 v 的蓄水量时,需要保证:对于图中的每一条有向边 (u,v)u 的蓄水量都被松弛过了。

发现可以通过拓扑序来转移。

T2. 字符串匹配

LOJ #3387

Solution

算法一

部分分:n217

一个较为简单的做法,基本不用怎么思考。

注意到答案是要求将字符串划分成 S=(AB)iC 的形式。

F(S) 的表示字符串 S 中出现奇数次的字符的数量。需要先预处理出:

  • 每一个前缀 S1..i 出现奇数次的字符的数量,即 F(S1..i)
  • 每一个后缀 Si..n 出现奇数次的字符的数量,即 F(Si..n)

考虑枚举 T=(AB),那相当于是枚举一个前缀。此基础上,再从小到大枚举一个 i,使用 hash 判断子串是否完全相等。

此时整个字符串的划分结构就已经是确定的了。F(C) 已经预处理好了,那这种情况对答案的贡献,相当于要在 T 里数出有多少个真前缀 A 满足 F(A)F(C),那直接用树状数组动态维护一下即可。

时间复杂度 O(nlogn+nlog||),其中 表示字符集。期望得分 84100

算法二

「算法一」没有怎么用到题目中的一些性质,还是考虑枚举 T=(AB)=S1..x

对于当前枚举到的一个 x。考虑计算出一个最大的 i,使得 S 可以被划分成 (AB)iC 的形式,记这个量为 k

引理:若一个长度为 n 的字符串 S 的前 nm 位和后 nm 是相等的且 mn,则 S 有一个长度为 m 的整除循环节。

根据该引理,考虑求出字符串 SZ 函数,其中 Zi 表示:后缀 Si..nS 的最长公共前缀(LCP)的长度。

注意到若 S 可以被划分成 (AB)iC 的形式,则必满足 x(i1)Zx+1xi<n。解得

iZx+1x+1i<nx

k=min{Zx+1x+1,nx1}

接下来考虑 F((AB)i) 的重复性,注意到:

  • i 为奇数时 F((AB)i) 均等。当 i 为奇数时,对于每个 (AB)i 划分出来的 C,都有 F(C)=F(Sx+1..n)

  • i 为偶数时 F((AB)i)=0。当 i 为偶数时,对于每个 (AB)i 划分出来的 C,都有 F(C)=F(S)

那么我们可以知道,划分出来的 F(C) 的也就只有两种情况,要么是 F(Sx+1..n) 要么是 F(S)。其中 k2i 为奇数,k2i 为偶数。

F(Sx+1..n) 在枚举 x 的时候顺便处理一下即可,F(S) 直接处理即可。

那么现在就是要分别数出 T 中有多少个真前缀 A 满足 F(A)F(Sx+1..n)F(A)F(S)

注意到 F(S) 是不变的,那么在枚举的时候直接判断一下即可。至于 F(Sx+1..n),当 x1 的时候也只会导致 F(Sx+1..n) 变化 1,稍微判断一下补补贡献即可。

时间复杂度 O(n)

T3. 移球游戏

LOJ #3388

Solution

感谢 xyz32768 的指导,以及他的题解

算法一

部分分:n=2

现在有三个柱子 x,y,z。 其中 x 号柱与 y 号柱是满的,z 号柱是空的。这 2m 个球中有 m 个关键球,现在要将所有关键球移动到同一根柱子上。

x 柱上有 c 个关键球,操作如下:

  • (1):将 y 号柱上的 c 个球移动到 z 号柱上。

  • (2):依次考虑 x 号柱里的每一个球。

    若该球为关键球,则将其移动到 y 号柱。
    若该球不为关键球,则将其移动到 z 号柱。

  • (3):将 z 号柱上方的 mc 个球移回 x 号柱。

  • (4):将 y 号柱上方的 c 个球移动到 x 号柱。

  • (5):将 z 号柱里的 c 个球移动到 y 号柱。

  • (6):将 x 号柱上方的 c 个球移动到 z 号柱。

  • (7):依次考虑 y 号柱里的每一个球。

    若该球为关键球,则将其移动到 z 号柱。
    若该球不为关键球,则将其移动到 x 号柱。

此时 n=2 就做完了,复杂度是 O(m) 的。

「算法一」是本题中最基本的操作

算法二

部分分:n50m300

可以一个颜色一个颜色来考虑。假设考虑到第 n 个颜色,现在要将所有颜色为 n 的球移动到同一根柱子上:

  1. 枚举 i=1(n1),将 i 号柱里所有颜色为 n 的球都移动到 i 号柱子的最顶端。记 i 号柱共有 ci 个颜色为 n 的球,操作如下:

    • (1):将 n 号柱移出 ci 个空位。

    • (2):依次考虑 i 号柱里的每一个球。

      若该球的颜色为 n,则将其移动到 n 号柱。
      若该球的颜色不为 n,则将其移动到 n+1 号柱。

    • (3):将 n+1 号柱上方的 mci 个球移回 i 号柱。

    • (4):将 n 号柱上方的 ci 个球移回 i 号柱。

    • (5):将 n+1 号柱上方的 ci 个球移回 n 号柱。

  2. 枚举 i=1(n1),将 i 号柱子最顶端所有颜色为 n 的球都移动到 n+1 号柱上。

  3. 依次考虑 n 号柱子里的每一个球。

    若该球的颜色为 n,则将其移动到 n+1 号柱。
    若该球的颜色不为 n,则将其补到 1n1 号柱里的一个空位上。

这样的话就得到了一个规模为 n1 的子问题,直接递归即可。

复杂度是 O(n2m) 的。可以计算得出该算法最坏情况下的严格操作数为 m(n1)(n+4)

发现刚好可以过掉 70 分。

算法三

注意到「算法二」中,一个颜色一个颜色来考虑有点浪费。可不可以多个颜色一起考虑呢?这启发我们分治。

定义分治函数 solve(l, r),取中点 mid=l+r2

在每一轮中我们的目的是:将所有 " 颜色 mid 的球 " 与 " 颜色 >mid 的球 " 区分开来。
即:经过一系列操作过后,不存在一根柱子上同时有 " 颜色 mid 的球 " 和 " 颜色 >mid 的球 "。

随后调用 solve(l, mid)solve(mid + 1, r)

问题的关键在于如何区分。

在每一轮中,我们将这 rl+1 根柱子取出来。每次我们可以挑出两根柱子:

  • (1):如果 " 颜色 mid 的球 " 超过了 m 个。
    则选取任意 m 个 " 颜色 mid 的球 " 作为关键球,进行「算法一」中的基本操作。
  • (2):如果 " 颜色 >mid 的球 " 超过了 m 个。
    则选取任意 m 个 " 颜色 >mid 的球 " 作为关键球,进行「算法一」中的基本操作。

这样进行 rl 次,这 rl+1 根柱子也就达到了每一轮的目的,递归下去解决即可。

考虑分治树的结构,共有 O(logn) 层。对于每层的所有节点,进行上述的基本操作的复杂度是 O(nm) 的。

时间复杂度为 O(nmlogn)

T4. 微信步数

LOJ #3389

Solution

算法一

部分分:wi106

不难想到,可以考虑计算 " 走完了第 i 步后恰好走出场地 " 的所有点对答案的贡献。

为了方便叙述,约定:

  • 一个周期:前 n 步组成的路线。
  • Li:在第 i 个维度上,当前仍然在场地内的点的坐标的最小值。
  • Ri:在第 i 个维度上,当前仍然在场地内的点的坐标的最大值。
  • v:经过了一个周期后的位移向量;vi:位移向量 v 在第 i 个维度上的位移。

引理 1

若会出现某一个点死循环,则满足以下两个条件。

(1):经过了一个周期后,存在一个点没有走出场地。

(2):v=0

证明

必要性:显然。

充分性:考虑满足(1)的点,因为 v=0,所以无论走了多少个周期,该点始终呆在原地,也不会在走周期的过程中走出场地。故出现死循环。

故命题得证,QED。

考虑一下什么情况下会对答案造成贡献。

引理 2

若第 i 步对答案有贡献,则当前在第 ci 维上的位移,一定是向 " 正方向 " 走或向 "反方向 " 走的历史位移最大值(即可以更新 LciRci)。

证明

考虑 LiRi 的定义,不难发现:在第 ci 维中,所有离开场地的点的坐标一定在 [1,Lci)  (Rci,wci] 内。

那么,若第 i 步后 LciRci 没有得到更新,那么 [1,Lci)  (Rci,wci] 是不会变的,故离开场地的点的集合也没变。故在该种情况下,第 i 步不对答案造成贡献。

进一步分析可知:若第 i 步后 LciRci 得到了更新,那么这一批离开场地的点的坐标均为更新后的 Lci1Rci+1

故命题得证,Q.E.D

考虑一下该种情况下会造成多少贡献。

引理 3

若第 i 步对答案有贡献,则该贡献值为 i×jci(RjLj+1)

证明

对于第 ci 维,这一批离开场地的点的坐标均为更新后的 Lci1Rci+1

对于除了第 ci 维的任意一个维度,现在考虑第 p 维。
显然,这一批离开场地的点的坐标可以在 [Lp,Rp] 中任意做选择。

根据乘法原理,这一批离开场地的点共有:

(R1L1+1)××(Rci1Lci1+1)×1×(Rci+1Lci+1+1)××(RkLk+1)

即为:

jci(RjLj+1)

将上式乘上 i,即为第 i 步对答案的贡献值。

故命题得证,Q.E.D

至此,我们已经有方法可以计算出正确的答案。只不过,要是直接枚举 i 的话,时间复杂度是不能接受的。

我们还没有利用到移动路线的 " 周期性 ",接下来就来讨论一下 " 周期性 " 在本题中的特殊效果。为了方便叙述,我们称可以对答案造成贡献的一步为 " 特殊步 "

引理 4

(1):当第一周期中的第 i 步为 " 特殊步 " 时:

  • 则第二周期中的第 i+n 步,第三周期中的第 i+2n 步,...,均不一定为 " 特殊步 "。

(2):当第一周期中的第 i 步为 " 特殊步 ",且第二周期中的第 i+n 步也为 " 特殊步 " 时:

  • 第三周期中的第 i+2n 步,第四周期中的第 i+3n 步,...,一定均为 " 特殊步 "。

引理 4 的推论

第一周期中 " 特殊步 " 的分布是特殊的; 第二、三、四、... 周期中 " 特殊步 " 的分布是相同的。

根据引理 4 的推论,我们可以先计算出第一周期中 " 特殊步 " 对答案的贡献。

对于第二、三、四、... 周期,考虑步数模 n 的结果,对于模 n 的所有同余类 1¯,2¯,,n1¯,0¯,我们可以分别计算每个同余类对答案的贡献。

引理 5

设当前进行到了第 i 步,若进行到了第 i+n 步时,该点还在场地内,对于第 j 维的变化是:

(1):若 vj>0,则 LjLj+|vj|

(2):若 vj<0,则 RjRj|vj|

(3):对于 RjLj+1,其值将会变化为:

(RjLj+1)|vj|

证明

不难发现,若 " 进行到第 i+n 步时,该点还在场地内 "。

则 " 前 i 步组成的路径 " 与 " 前 i+n 步组成的路径 " 之间只差了一个周期位移向量 v
(在该情况下,位移的先后顺序不影响最终结果)

那么,在只考虑第 j 维的情况下。

相当于进行到了第 i 步,然后又经过了一个周期后,坐标值被加上了 vj

故命题得证,Q.E.D

引理 5 的推论

对于第二周期中的第 i 步(其中 n<i2n),若第 i 步是一个 " 特殊步 "。

考虑第 nx+(in) 步,若该步也是一个 " 特殊步 ",则该步对答案的贡献为:

[n×(x1)+i]jci[|vj|×(x1)+(RjLj+1)]

即:

[n×x+(in)]jci[|vj|×x+(RjLj+1+|vj|)]

至此,已经有了一个初步的做法。

枚举 i=1n,先计算出第一周期中 " 特殊步 " 对答案的贡献。

再枚举 i=(n+1)2n,计算每个模 n 的同余类 in¯ 对答案的贡献。具体地,根据引理 5 的推论,在循环内部再枚举一个 x 即可。

时间复杂度玄学,上界是 O(nk×max1ik{wi}),但实际上远不能达到上界,所以可以拿到可观的 80 分。

算法二

特殊性质:wi109

看起来「算法一」非常有前途,考虑优化。优化的重点其实在于计算模 n 的所有同余类 1¯,2¯,,n1¯,0¯ 对答案的贡献。

对于第二周期中的第 i 步(其中 n<i2n),若第 i 步是一个 " 特殊步 "。

考虑第 nx+(in) 步,若该步也是一个 " 特殊步 ",则不难发现,该步对答案的贡献是一个与 x 有关的多项式,可以考虑用 f(x) 表示:

f(x)=[n×x+(in)]jci[|vj|×x+(RjLj+1+|vj|)]

注意到 f(x) 的每个乘积项,都是关于 x 的一次二项式。

可以考虑将这 k 个乘积项卷在一起,即可得到一个 k 次多项式 f(x)。至于计算出 f(x) 的系数,直接暴力卷即可,因为 k 很小,所以复杂度肯定是可以接受的。

多项式乘法(卷积):

  • 给定两个多项式 f(x)g(x)

f(x)=i=0nai×xi

g(x)=j=0mbj×xj

  • 要计算多项式 Q(x)=f(x)×g(x)

Q(x)=i=0nj=0mai×bj×xi+j

考虑计算贡献。设模 m 的同余类 i¯ 从第二周期开始,最多要计算到第 E 轮,不难得到:

E=min1ik,vi0{RiLi|vi|+1}

此时贡献为:

x=1Ef(x)

f(x)i=0kai×xi 替换,得:

x=1Ei=0kai×xi

交换枚举顺序,得:

i=0k(ai×x=1Exi)

至于要快速计算函数 Sk(n)=i=1nik,是一个非常经典的问题。详见 CF622F The Sum of the k-th Powers

本篇题解中,代码给出的是 " 拉格朗日插值 "。

代码中并没有直接拉格朗日插值,而是使用拉格朗日插值先预处理出 Sk(n) 所对应的关于 nk+1 次多项式,然后再代入 x 进行计算。

时间复杂度 O(nk2)

posted @   Calculatelove  阅读(1177)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示