第20届宁波大学程序设计竞赛-题解

难度预测:

easy:BDH

middle:EFGK

middle-hard:A

hard:CIJ

Problem A. 0-1翻转

知识点:贪心

对于每次操作,可以发现奇数位的 0011 与偶数位的 0011 同时增加或减少,所以奇数位和偶数位 0011 的数量差不变。要想把数全变成 00 的充分必要条件,是奇数位的 11 和偶数位的 11 数量相等。要想把一个奇数位的 11 和一个偶数位的 11 全变成 00,需要进行操作的最少次数为这两个 11 之间的距离。

所以,我们只需要最小化奇数位和偶数位 11 之间的距离,考虑贪心,将奇数位和偶数位 11 的位置分别按从小到大排序,然后从小到大枚举 11 之间的距离,统计贡献求和,可以保证操作次数最少。我们可以在 O(n)O(n) 的时间复杂度下,求出结果。

Problem B. 类银河恶魔城

知识点:贪心,排序

对于每款游戏而言,剩下的 一项艺术性指标如果是 100100 分,并且其他游戏都是 00 分,这样自己的排名能够更靠前。所以只要比较每款游戏已经确定的分数与排名第 KK 的游戏的分数差,能否用艺术性指标的 100100 分追回即可,实现该操作只需要对总分进行排序。因为数据范围很小,可以直接冒泡排序或者选择排序,时间复杂度为 O(n2)O(n^2)O(nlogn)O(nlogn)

Problem C. 平泽唯删圆

知识点:计算几何,最大生成树,拓扑排序

首先,注意到 nn 的范围只有 500500,考虑预处理出每两个圆重叠部分的面积,两圆相交面积直接调用板子即可。将每个圆的圆心看作点,两个圆重叠部分的面积看作边权,通过边连接这两点,于是该题可转化为图论问题,不难发现该图是 nn 阶完全图。

然后,每次操作相当于选一个点和连向该点最大边权的边,要想使分数最大化,选出的点和边一定是构成该图的最大生成树。又因为任意两个圆重叠部分面积均不同,所以最大生成树一定唯一。

最后,考虑如何安排删圆的顺序,删圆相当于删点,每次删的点的度数一定为 11 (最后一个点除外)。不难想到拓扑排序,但是要求字典序最小,可以考虑使用优先队列维护进行 bfsbfs,时间复杂度 O(nlogn)O(nlogn)。因为 nn 的范围只有 500500,所以也可以直接 O(n2)O(n^2) 暴力贪心,我们每次从小到大找到第一个能删的点删除,同时将与该点相连的点的度数减 11,这样得到的删点顺序的字典序一定最小。

总的时间复杂度 O(n2logn)O(n^2logn)

Problem D. 翔子小姐学均值不等式(easy version)

知识点:枚举

注意到 x,yx,y 的数据范围很小,可以考虑暴力枚举 (a,b)(a,b) 的值(注意枚举的范围),时间复杂度 O(n2)O(n^2)

Problem E. 翔子小姐学均值不等式(hard version)

知识点:二分

因为 x,yx,y 的数据范围很大,直接枚举显然超时,考虑二分优化。由题意可知,不等式中间部分 21a+1baba+b2a2+b22\frac{2}{\frac{1}{a}+\frac{1}{b}}\leq \sqrt[]{ab}\leq \frac{a+b}{2}\leq \sqrt[]{\frac{a^2+b^2}{2}} 恒成立,所以我们只需要满足 x21a+1bx \leq \frac{2}{\frac{1}{a}+\frac{1}{b}}a2+b22y\sqrt[]{\frac{a^2+b^2}{2}} \leq y 两边即可,式子进一步化简可得 (a+b)x2ab(a+b)x \leq 2aba2+b22y2a^2+b^2 \leq 2y^2,由于两者都具有单调性,所以我们可以先枚举 aa 的值,再对 bb 的值进行二分查找,分别统计两个不等式 (a,b)(a,b) 的数量,取两者的交集即可,时间复杂度 O(nlogn)O(nlogn)

Problem F. 回文串

知识点:最短路,dp

普通魔法可以看作是一条从 aia_i 连向 bib_i 的有向边,边权为 cic_i。超级魔法可以看作是所有字母两两之间连了一条边权为 ww 的无向边。现在要把字符串 ss 变为回文串,就是要把 sis_isni+1s_{n-i+1} 都变成同一种字母。

f[a][b]f[a][b] 表示把字母 aa 变成字母 bb 需要消耗的最小法力。可以用 Floyd 求出所有的 f[i][j]f[i][j]

而把 a,ba,b 都变成同一种字母既可以是都变成 aa,也可以是变成 bb,还可以是都变成另一种字母 cc。因此需要考虑 g[a][b]g[a][b] 表示把字母 aa 和字母 bb 都变成同一种字母需要消耗的最小法力,这也可以用类似 Floyd 的方法求出。

Problem G. 雫露露的背包

知识点:深度优先搜索(DFS)

考虑深度优先搜索(DFS)算法,我们可以将所有取法的情况全部算一遍,如果某个取法能够恰好装满背包,则答案加1。因为 aia_i 的总乘积不超过 10610^6,所以枚举所有取法的情况不会超时。

Problem H. 樱花庄的樱花树

知识点:树,数学

不难得出,节点 xx 的三个子节点分别是 3x1,3x,3x+13x-1,3x,3x+1;节点 xx 的父节点是 x+13\lfloor \frac{x+1}{3} \rfloor (向下取整)。为了求出两点的最近公共祖先,可以每次找节点编号比较大的那个点,让它向上跳。显然在树上,这两个点最后一定会相遇,相遇的位置就是我们想要求的 LCALCA。因为完全三叉树的树高为 O(logn)O(logn),所以单次查询时间复杂度为 O(logn)O(logn)

Problem I. 库洛牌小喵钓鱼

知识点:概率 dpdp,前缀和优化

dpidp_i 表示剩余 ii 张花色牌时 TomoyoTomoyo 获胜的概率。洗牌后,dpidp_i 可以转移到 dpi,dpi1,dpi2,...,dp0dp_i,dp_{i-1},dp_{i-2},...,dp_0。于是我们可以得出,当 i2i \ge 2 时的状态转移方程:

dpi=2(i+1)(i+2)j=0i(i+1j)dpj\begin{aligned} dp_i=\frac{2}{(i+1)(i+2)}\sum_{j=0}^{i}(i+1-j)dp_j \end{aligned}

注意到其中 j=0i(i+1j)dpj\sum_{j=0}^{i}(i+1-j)dp_j 的部分可以用前缀和表示,于是我们可以先根据 dp0=1dp_0=1dp1=0dp_1=0,在 O(nlogn)O(nlogn) 时间复杂度下进行预处理,递推得到所有 dpdp 的值,然后 O(1)O(1) 处理每组数据,总的时间复杂度为 O(nlogn)O(nlogn)

Problem J. 双端队列

知识点:树状数组

如果直接使用双端队列虽然可以很快完成操作1、2、4,但是执行删除操作很慢,因此考虑使用树形结构来维护。

可以用权值树状数组维护第 ii 个位置上是否有数。

对于操作1、2,维护左右端点 l,rl,r,表示当前已使用的树状数组下标范围为[l,r][l,r],初始状态 l=q,r=q+1l=q,r=q+1,执行操作1或2就把树状数组 llrr 位置上的值修改为1;同时对每个数都记录 pospos,用于保存这个数每一次插入到树状数组的位置。

对于操作3,取出 xx 最后一次插入的位置 laslas,直接对树状数组的 laslas 位置进行修改,这样每次删除只影响1个位置,其他数字的位置仍然不变。

对于操作4,因为使用的是权值树状数组,要想找到第 xx 个有数的位置,就是要在树状数组上找到前缀和等于 xx 的第一个位置,因此一种可行的方法是二分位置 pp,每次对树状数组求 sum(p)sum(p),这样一次操作的复杂度为 O(logn)O(logn),本题时限较宽松,只要常数不是太大都是可以通过的。

此外,还可以使用树状数组树上倍增求第 kk 小值的方法以 O(logn)O(logn) 的复杂度完成一次查询。

Problem K. 多拉博弈

知识点:博弈论

题意可以化简为有数量分别为 x1x0x_1-x_0y1y0y_1-y_0 的两堆石子,每次操作相当于从其中一堆石子中取 1133 颗石子,取走任意一堆的最后一颗石子的人输掉游戏。

假设两堆石子的数量分别为 a,ba,b。易知,当 (a,b)(a,b)(1,1)(1,1) 时,先手必输,所以 (1,1)(1,1) 为必败状态。又因为当先手从任意一堆中取 kk 颗石子,后手可以从另一堆中也取 kk 颗石子,所以 (n,n)(n,n) 也为必败状态。

又因为每次操作取 1,2,31,2,3 颗,所以无论先手取多少颗,后手总能保证共同从一堆石子中取走 44 颗,于是 (n,n+4),(n,n+8)......(n,n+4),(n,n+8)......也属于必败状态,同理,一般化后得到 (n+4k1,n+4k2)(n+4k_1,n+4k_2)也属于必败状态,而其他状态则属于必胜状态。

所以如果两堆石子的数量差为 44 的倍数,即 ab mod 4=0|a-b| \ mod \ 4 = 0,则先手必败,否则,先手必胜。