【比赛题解】CSP2020 提高组题解

 


T1. 儒略日

LOJ #3379

Solution

首先为了方便讨论,先令 rr+1,这样的话,求的就是 " 第几天 " 而不是 " 经过了几天 " 了。

显然可以考虑把 " 时间轴 " 分成一些 " 时间段 ",在每一段中根据 " 日期变化的周期性 " 计算答案。

但是这个做法比较 naive,有没有更给力点的?有没有更加短小精悍的?

那当然还是有的:

  1. 对于 4713.1.1 BC1600.12.31 的每一个日期,可以通过 " day by day " 的方式将答案先预处理出来。
  2. 对于 1601.1.1 及以后的每一个日期,可以通过 " 日期变化的周期性 " 来计算答案。

这样子做会少讨论许多的情况,比较好写。

T2. 动物园

LOJ #3380

Solution

注意到对于所有的约束关系 (pi,qi),所对应的 qi 是互不相同的。

那么,也就是说,如果我这里有一个动物编号,其中的第 i 位存在约束关系,那我的第 i 位就会固定的影响到清单中的若干位。

约定变量:

  • matchj:表示第 j 位是否存在约束关系。
  • existj:表示是否存在一个 ai,满足 ai 的第 j 位为 1

那么当我们新加进去一个动物时,考虑每一位的取值。
显然第 j 位填 0 是可以的,因为这样不可能会影响到清单。
如果第 j 位填 1,当且仅当满足以下 2 个条件之一:

  1. matchj=0
  2. matchj=1existj=1

第一条显然。第二条指的是:虽然第 j 位存在约束关系,但是已经存在一个动物编号影响到了清单,那么我第 j 位填 1 也不会再次影响到清单了。

记 " 有多少位可以填 1 " 的数量为 fre,根据乘法原理,一共可以养 2fre 个动物。

但是题目问的是 " 还可以养多少个 ",可以证明,养过的 n 个动物一定被包含在这 2fre 之内。

故答案即为 2fren

这题数据范围比较***钻,有几个 X 点:

  1. k == 64 && n == 0 && m == 0 :会爆 unsigned long long,需要特判,直接输出 264 即可。
  2. fre == 64:使用 1ull << 64 时会爆炸,可以输出 (1ull << 63) - n + (1ull << 63)

T3. 函数调用

LOJ #3381

Solution

不难看出,如果我把每个函数看成一个点。
那么对于每个 Tj=3 的函数 j,我让 jg1(j),g2(j),...,gCj(j) 连边的话,会得到一张 DAG。

记 " 调用函数 i 会使全局乘多少倍 " 为 muli,该数组可以在 DAG 上记忆化搜索求出。

注意到影响到答案最后取值的操作只有 " 单点加 " 和 " 全局乘 " 两种操作。
那么我可以尝试把最终序列上,第 i 个位置上的数表示为下列该式的形式:

ai×b+ki

其中:

  • ai 表示:初始序列中第 i 个位置上的值。
  • b 表示:所有操作结束后," 全局乘 " 的倍数。
  • ki 表示:所有 " 单点加 " 操作对第 i 个位置的贡献。

那现在关键是在于如何求出每个 ki

一个重要的思想是:如果我进行了一次 " 值为 a 的单点加 ",然后我进行了一次 " 值为 b 的全局乘 ",那么我可以看作是进行了 b 次 " 值为 a 的单点加 "。

记 " 函数 i 进行了多少次 " 为 fi,对于每次调用,先在节点上打上标记,最后再用拓扑排序向下传递贡献。

具体地,倒序处理每一个调用(因为只有时间更靠后的 " 全局乘 " 才能影响到 " 单点加 "),假设说我这次要调用第 i 个函数,那么:

  • fifi+b
  • bb×muli

然后考虑拓扑排序,假设说我这次要处理第 i 个函数,那么:

  • Ti=1,则令 kPikPi+Vi×fi
  • Ti=2,则无视该操作。
  • Ti=3,则倒序处理每一个调用,假设说我现在要将贡献传递给函数 j,那么:
    • fjfj+fi
    • fifi×mulj

拓扑排序完直接输出 ai×b+ki 即可。

时间复杂度 O(n+m+Q)

T4. 贪吃蛇

LOJ #3382

Solution

算法一

部分分:n5×104

先是一个引理 1:

引理 1

那么我们将蛇分成 " 没有被操作过 " 和 " 被操作过 " 两类。 现最强蛇操作后成为最弱蛇的局面之前,捕食后产生的蛇的强度是单调递减的。

即,捕食后产生的蛇中,先产生的蛇强于后产生的蛇。

证明

在保证没有出现最强蛇操作后成为最弱蛇的情况下。显然,当前的最强蛇没有上次操作时的最强蛇强,当前的最弱蛇也没有上次操作时的最弱蛇弱。根据不等式基本性质可知,当前产生的新蛇的实力值一定不大于上次操作时产生的蛇的实力值。

又由于给出来的实力值序列 {an} 满足 a1a2an1an

那么我们将蛇分成 " 没有被操作过 " 和 " 被操作过 " 两类。

将第一类蛇取出来的顺序肯定是按照 n,n1, 这样编号递减的顺序取出来的。

由于将第一类蛇取出来后就会变成第二类蛇,所以第二类蛇产生的顺序也是按照 n,n1, 这样编号递减的顺序产生的,由于捕食后产生的蛇的实力值是单调递减的,所以将第二类蛇取出来的顺序自然也是按照 n,n1, 这样编号递减的顺序取出来的。

所以,即使是在权值相等的情况下,当前产生的新蛇的编号也一定不大于上次操作时产生的蛇的编号。

故当前产生的新蛇的强度一定不大于上次操作时产生的蛇的强度,引理 1 得证。

又是一个引理 2:

引理 2

在出现最强蛇操作后成为最弱蛇的局面之前,若一个最强蛇操作后不会成为最弱蛇,那么这条最强蛇一定会无脑进行该次操作。

证明

设当前有一条最强蛇 A

(1):如果这个最强蛇 A 操作后还是最强蛇。那当然吃就完事了。

(2):如果这个最强蛇 A 操作后会有另一条蛇 B 取代了它最强的位置。由于我们假设的大前提,蛇 A 不会成为这次蛇 B 操作的目标。根据引理 1,蛇 B 进行该次操作后,强度一定不如操作过后的蛇 A。故蛇 B 成为狩猎对象的优先级一定高于蛇 A。在题目给定的 " 所有蛇均采取最优策略 " 的博弈背景下,蛇 B 会在不让自己死的前提下采取最优策略,那么蛇 A 肯定也不会死。

综上所述,引理 2 得证。

有了引理 1 和引理 2,可以考虑做一些事情。

注意到,不论蛇是怎么进行选择,每一轮中的捕食者与被捕食者都是不会发生变化的。

根据引理 2,在出现最强蛇操作后成为最弱蛇的局面之前,所有的局面都可以无脑的进行下去。

那重点就在于,第一次出现最强蛇操作后成为最弱蛇的局面。
现在要讨论该操作是否进行,就出现了蛇之间的千层博弈:

  • 当前有蛇 A,B

    • A 操作后成为了最弱蛇。
    • B 吃了蛇 A 后不会成为最弱蛇。

    考虑到蛇 A 进行了该次操作后会被蛇 B 无脑吃掉,那么蛇 A 不该进行这次操作。

  • 当前有蛇 A,B,C

    • A 操作后成为了最弱蛇。
    • B 吃了蛇 A 后成为了最弱蛇。
    • C 吃了蛇 B 后不会成为最弱蛇。

    考虑到蛇 B 吃了蛇 A 后自身难保,那么蛇 A 就会预判蛇 B 不敢吃它,那么蛇 A 就可以放心进行该次操作。

  • ......

亦可以归纳证明,当第一次出现最强蛇操作后成为最弱蛇的局面时,该次操作是否进行,与 " 最强蛇操作后成为最弱蛇 " 这样的局面连续进行了多少次的奇偶性有关。若为偶数,那么该次操作可以放心进行;若为奇数,那么该次操作便不该进行。

讨论到这里,本题就有了一个初步的做法,分成 Part 1 与 Part 2:

  • 在 Part 1 中:模拟操作,若第 i 步进行后最强蛇会成为最弱蛇,则进入 Part 2。

  • 在 Part 2 中:模拟操作,统计 " 最强蛇操作后成为最弱蛇 " 这样的局面连续进行了多少次。
    若为偶数,则答案为 ni;若为奇数,则答案为 ni+1

使用线段树或平衡树随意维护一下蛇,回答单次询问的时间复杂度是 O(nlogn) 的,期望得分 70

算法二

从数据范围中亦可猜得标算是一个线性的做法。从输入格式中亦可猜得标算充分利用了 {an} 的单调性,不然时间复杂度的瓶颈就会在排序上。

优化方式便是类似 「NOIP2016 提高组」蚯蚓 中的利用数据独特的单调性,配合队列来维护最值的方法。

具体的,开两个队列 Q1,Q2。其中 Q1 维护的是 " 没有被操作过 " 的蛇。Q2 维护的是 " 被操作过 " 的蛇。且 Q1,Q2 中的蛇均按强度递减的顺序存放。

根据定义,最强蛇便是 Q1,Q2 中队首中的较大值,最弱蛇便是 Q1,Q2 中队尾中的较小值。

相较于算法一中,不同的地方在于:

  • 在 Part 1 中:我们每次取出最强蛇与最弱蛇,然后进行该次操作,新产生的蛇直接放到 Q2 的队尾即可,根据引理 1,不失单调性。

  • 在 Part 2 中:我们每次取出最强蛇与最弱蛇,先是判断该次操作后最强蛇是否会成为最弱蛇,若最强蛇会成为最弱蛇,那么将新产生的蛇直接放到 Q2 的队尾即可,根据最弱蛇的定义,不失单调性。

这样就可以使用队列来维护蛇了,回答单次询问的时间复杂度是 O(n) 的,十分优秀。

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