20210705组队赛 题解

20210705组队赛 题解


前言

目前已施工完毕,欢迎阅读!

本题解中略去大部分 题意简述 部分,如需了解题意请阅读原题面。


A - 最大的序列

非本校OJ题目传送门

题目分析

想法 1 1 1:我会暴力!

枚举每个数是否取,然后计算和并对 m m m 取模,直接二进制为 O ( n 2 n ) O(n2^n) O(n2n),如果写 DFS 边取边统计就是 O ( 2 n ) O(2^n) O(2n),期望得分 50 50 50 分。

想法 2 2 2:我会折半搜索!

观察到 n ≤ 35 n\le 35 n35,如果将原数列先拆为两半分别搜索,再通过某种方法进行合并,可以大幅降低复杂度。

p p p 为由前一半 DFS 得到的和构成的数组 A A A 中的一个元素, q q q 为由后一半 DFS 得到的和构成的数组 B B B 中的一个元素。那么显然有 0 ≤ p , q < m 0\le p,q0p,q<m,从而 p + q < 2 m p+q<2m p+q<2m。而答案为 max ⁡ { ( p + q ) m o d    m } \max\{(p+q)\mod m\} max{(p+q)modm},因此我们对 p + q p+q p+q 进行分类讨论。

  1. m ≤ p + q < 2 m m\le p+q<2m mp+q<2m

    显然 p + q p+q p+q 越大越好,直接取最大的 p p p 和最大的 q q q 即可。

  2. 0 ≤ p + q < m 0\le p+q0p+q<m

    两种做法,前提都是两个数组都有序。(此处默认单调不降)

    • 二分。枚举 A A A 中的元素,二分找到 B B B 中最大的元素使得 p + q < m p+qp+q<m。时间复杂度为 O ( n log ⁡ 2 n ) O(n\log_2{n}) O(nlog2n)
    • 双指针。由于 A A A 中元素单调不降,所以对应的 B B B 中的满足 p + q < m p+qp+q<m 的最大元素单调不升。因此用另一个指针 j j j 从尾到头一遍扫数组 B B B,即可找到答案。时间复杂度为 O ( n ) O(n) O(n)

时间复杂度为 O ( 2 n / 2 ) O(2^{n/2}) O(2n/2),因为统计部分复杂度远比这低。期望得分 100 100 100 分。

代码展示

https://www.luogu.com.cn/paste/ey4ot8x2

提供了两种方法的代码。


B - 礼物

非本校OJ题目传送门

题意简述

一张图,每条边有两个属性 ( g i , s i ) (g_i, s_i) (gi,si) 。给定 G , S G, S G,S,求一棵图的生成树 T T T,使得 G × max ⁡ ( g i ) + S × max ⁡ ( s i ) G \times \max(g_i) + S \times \max (s_i) G×max(gi)+S×max(si) 最小 ( i ∈ T ) (i\in T) (iT)。图可能包含重边和自环。

题目分析

最小生成树优化。

如果只有金币怎么做?将金币从小到大排序,直接跑最小生成树即可。

那再加上银币呢?枚举 max ⁡ ( g i ) \max(g_i) max(gi),将所有 g i ≤ max ⁡ ( g i ) g_i\le \max(g_i) gimax(gi) 的边抽出跑最小生成树,时间复杂度为 O ( m 2 ) O(m^2) O(m2),无法通过此题。

注意到枚举 max ⁡ ( g i ) \max(g_i) max(gi) 的过程中,构成最小生成树的边集中只会加入 s i s_i si 更小的边,删去 s i s_i si 更大的边。因此我们维护一个边集,边集中的边按照 s i s_i si 从小到大排序,每次插入一条边。这一过程可以用归并排序实现,时间复杂度为 O ( m n log ⁡ 2 n ) O(mn\log_2n) O(mnlog2n)

这一过程也可以用冒泡排序实现,每加入一条边就从后往前冒泡,以此来维护一个 s i s_i si 单调不降的边集,时间复杂度为 O ( m n ) O(mn) O(mn)

而在每次做最小生成树时,我们需要将加入的边放入新边集,从而满足上述过程的需求。

代码展示

https://www.luogu.com.cn/paste/cczt8pxz


C - Do You Know Your ABCs?

非本校OJ题目传送门

题目分析

码农题。

注意到 A,B,C \text{A,B,C} A,B,C 满足以下关系:

20210705组队赛 题解_第1张图片

其中 C \text{C} C A+B \text{A+B} A+B 的大小关系不确定。

因此我们将输入的 x x x 数组从小到大排序,然后 DFS 枚举一下 x x x 数组中的每个值属于原始序列的哪一个。计算时将位置 3 3 3 4 4 4 指向的值也算一遍就可以不考虑 C \text{C} C A+B \text{A+B} A+B 的大小关系了。

计算时默认位置 3 3 3 指向 C \text{C} C 的值,位置 4 4 4 指向 A+B \text{A+B} A+B 的值。考虑一下情况:

  1. A,B,C \text{A,B,C} A,B,C 的值知道 3 3 3 个。

  2. A,B,C \text{A,B,C} A,B,C 的值知道 2 2 2 个。

    • 知道 A,B \text{A,B} A,B。则 C \text{C} C 可以通过位置 5 , 6 , 7 5,6,7 5,6,7 上的任意一个值算出来。
    • 知道 A,C \text{A,C} A,C。则 B \text{B} B 可以通过位置 4 , 6 , 7 4,6,7 4,6,7 上的任意一个值算出来。
    • 知道 B,C \text{B,C} B,C。则 A \text{A} A 可以通过位置 4 , 5 , 7 4,5,7 4,5,7 上的任意一个值算出来。
  3. A,B,C \text{A,B,C} A,B,C 的值知道 1 1 1 个。

    • 知道 A \text{A} A。则 B \text{B} B 可以通过位置 4 4 4 直接得到, C \text{C} C 可以通过位置 5 5 5 直接得到,若 B \text{B} B C \text{C} C 已通过上面过程得知一个,可以通过位置 6 6 6 得知另一个。

    • 知道 B \text{B} B。则 A \text{A} A 可以通过位置 4 4 4 直接得到, C \text{C} C 可以通过位置 6 6 6 直接得到,若 A \text{A} A C \text{C} C 已通过上面过程得知一个,可以通过位置 5 5 5 得知另一个。

    • 知道 C \text{C} C。则 A \text{A} A 可以通过位置 5 5 5 直接得到, B \text{B} B 可以通过位置 6 6 6 直接得到,若 A \text{A} A B \text{B} B 已通过上面过程得知一个,可以通过位置 4 4 4 得知另一个。

  4. A,B,C \text{A,B,C} A,B,C 的值知道 0 0 0 个。

    由于 4 ≤ n ≤ 7 4\le n\le 7 4n7,那么位置 4 , 5 , 6 , 7 4,5,6,7 4,5,6,7 的值一定都已确定,直接计算即可。

通过上述方法得知 A,B,C \text{A,B,C} A,B,C 的值后,我们需要将其进行检验:

  1. 是否满足 A ≤ B ≤ C \text{A}\le \text{B}\le \text{C} ABC
  2. 是否符合搜索出来对应位置的值。

通过上述步骤就可以解决这道题目了。

代码展示

https://www.luogu.com.cn/paste/t4ilpt85


D - 游戏

非本校OJ题目传送门

题目分析

素数筛法+组合数学+期望。反正没想到,我是数学白痴实锤了。

定义 Key 数为不被区间 [ L , R ] [L,R] [L,R] 内任何其他数整除的数。题目就相当于求所有排列的最后一个 Key 数所在位置的总和。

用线性筛法(欧拉筛),我们预处理出区间内每个数的最小的非 1 1 1 因子 min ⁡ x \min_x minx,则最大的非本身因子 max ⁡ x = x m i n x \max_x=\dfrac{x}{min_x} maxx=minxx。如果 max ⁡ x < L \max_xmaxx<L,那么 x x x 就是 Key 数。若换用埃氏筛,实现更简单,但复杂度更高。

设共有 m m m 个 Key 数。

根据期望的性质,期望 = = = 概率 × \times × 贡献。设 p = p= p= 最后一个 Key 数在位置 i i i 的概率。

则有:

p = ( i − 1 m − 1 ) ( n − m ) ! m ! ( n m ) ( n − m ) ! m ! = ( i − 1 m − 1 ) ( n m ) = ( i − 1 ) ! ( m − 1 ) ! ( i − m ) ! × m ! ( n − m ) ! n ! = m ( i − 1 ) ! ( n − m ) ! ( i − m ) ! n ! \begin{aligned}p=&\dfrac{\dbinom{i-1}{m-1}(n-m)!m!}{\dbinom{n}{m}(n-m)!m!}\\=&\dfrac{\dbinom{i-1}{m-1}}{\dbinom{n}{m}}\\=&\dfrac{(i-1)!}{(m-1)!(i-m)!}\times \dfrac{m!(n-m)!}{n!}\\=&\dfrac{m(i-1)!(n-m)!}{(i-m)!n!}\end{aligned} p====(mn)(nm)!m!(m1i1)(nm)!m!(mn)(m1i1)(m1)!(im)!(i1)!×n!m!(nm)!(im)!n!m(i1)!(nm)!

而贡献则为 i × n ! i\times n! i×n!,即位置 × \times × 排列数。

那么期望为:

a n s = ∑ i = m n ( p × i ) × n ! = ∑ i = m n ( m ( i − 1 ) ! ( n − m ) ! ( i − m ) ! n ! × i ) × n ! = ∑ i = m n ( i ! ( i − m ) ! m ! ) × m × m ! × ( n − m ) ! = ∑ i = m n ( m i ) × m × m ! × ( n − m ) ! = ( m + 1 n + 1 ) × m × m ! × ( n − m ) ! = ( n + 1 ) ! ( m + 1 ) ! ( n − m ) ! × m × m ! × ( n − m ) ! = m ( n + 1 ) ! m + 1 \begin{aligned}ans=&\sum\limits_{i=m}^n{(p\times i)}\times n!\\=&\sum\limits_{i=m}^n\Bigg(\dfrac{m(i-1)!(n-m)!}{(i-m)!n!}\times i\Bigg)\times n!\\=&\sum\limits_{i=m}^n\Bigg(\dfrac{i!}{(i-m)!m!}\Bigg)\times m\times m!\times (n-m)!\\=&\sum\limits_{i=m}^n\dbinom{m}{i}\times m\times m!\times (n-m)!\\=&\dbinom{m+1}{n+1}\times m\times m!\times (n-m)!\\=&\dfrac{(n+1)!}{(m+1)!(n-m)!}\times m\times m!\times (n-m)!\\=&\dfrac{m(n+1)!}{m+1}\end{aligned} ans=======i=mn(p×i)×n!i=mn((im)!n!m(i1)!(nm)!×i)×n!i=mn((im)!m!i!)×m×m!×(nm)!i=mn(im)×m×m!×(nm)!(n+1m+1)×m×m!×(nm)!(m+1)!(nm)!(n+1)!×m×m!×(nm)!m+1m(n+1)!

上面 ∑ i = m n ( m i ) = ( m + 1 n + 1 ) \sum\limits_{i=m}^n\dbinom{m}{i}=\dbinom{m+1}{n+1} i=mn(im)=(n+1m+1) 的公式推导可以看 这篇题解。

简洁。

代码展示

https://www.luogu.com.cn/paste/817gdgw7


E - 小倍数

非校内OJ题目传送门

题目分析

神仙题,压根想不到。

需要对问题进行转化。每个数都能通过以下两种方式,从 1 1 1 得到。

  1. × 10 \times 10 ×10。这种方法即在原数末尾添一个 0 0 0,数位累加和不变,权重为 0 0 0
  2. + 1 +1 +1。这种方法数位累加和也会相应 + 1 +1 +1,权重为 1 1 1

然后使用 0-1 BFS 进行搜索,从 1 1 1 开始搜索,将权重为 0 0 0 的放入队首,为 1 1 1 的放入队尾,这样可以保证从队首到队尾的权重单调不减,从而使得找到的为 k k k 的倍数的数的权重一定最小。

代码展示

https://www.luogu.com.cn/paste/d87efwud


F - Acowdemia S

非本校OJ题目传送门

题目分析

二分水题。

贪心地想,将引用次数 c c c 数组总大到小排序,因此需要填补的引用次数就会尽可能地小,而更加容易满足条件。

直接二分 h h h,如果贪心填补需要的量超过 K × L K\times L K×L 或某一篇论文仍需引用的次数大于 K K K 即为不可行,否则可行。

时间复杂度为 O ( n log ⁡ 2 n ) O(n\log_2{n}) O(nlog2n),期望得分 100 100 100 分。

代码展示

https://www.luogu.com.cn/paste/xzp7mmkw


G - 云计算

非本校OJ题目传送门

题目分析

权值线段树。反正没弄出来,我是数据结构白痴实锤了。

很容易想到租借要价格递增地进行租借。这个区间有区间覆盖的感觉,但是不容易从中取出最小的 k k k 个。

用一种类似扫描线的思想,对于每种计划在 L i L_i Li 处增加 ( v a l i , c n t i ) (val_i,cnt_i) (vali,cnti),在 R i R_i Ri 处增加 ( v a l i , − c n t i ) (val_i,-cnt_i) (vali,cnti)。具体实现就是将这些二元组按照添加的时间从小到大排序,在对每一天进行操作时对应将这些二元组插入线段树即可。

查询部分用与 K-th number 类似的思想,如果左儿子对应的区间内的所有计划的租用 CPU 的总个数 ≥ k \ge k k,就在左儿子这边查找,否则在右儿子这边查找,然后再加上左儿子这边的总价即可。这被称为线段树上二分。

不会算时间复杂度 qwq

代码展示

https://www.luogu.com.cn/paste/vwhfv6bl


H - Portals

非本校OJ题目传送门

题意简述

给个 2 n 2n 2n 个点,和 n n n 个五元组 ( a , b , c , d , e ) (a,b,c,d,e) (a,b,c,d,e),最开始 a a a b b b 连边, c c c d d d 连边。对于每个五元组,可以花费 e i e_i ei 的代价将 a , b , c , d a,b,c,d a,b,c,d 重新排列,问最小的代价使所有点联通。每个点恰好出现两次。
数据范围: 2 ≤ n ≤ 1 0 5 2\le n\le 10^5 2n105 1 ≤ c v ≤ 1 0 3 1\le c_v\le 10^3 1cv103

题目分析

本文引用了 @SharpnessV 的 洛谷题解 中的较多语段。

最小生成树。

原题面长得要命。

抓住重点:每个点恰好出现两次

这意味着什么?这表示每个点的度数为 2 2 2,而连通的图如果每个点的度数为 2 2 2,则一定是一个环。如果图不连通,则是若干个环。

而合并这些环,可以用 e i e_i ei 的代价将 a i a_i ai 所在的环和 c i c_i ci 所在的环连通。因此我们只需要将先用并查集维护每个点所在的环,再将环缩成点,每个五元组缩成边,将这样组成的新图跑一遍最小生成树即可。

时间复杂度为 O ( n log ⁡ 2 n ) O(n\log_2n) O(nlog2n),期望得分 100 100 100 分。

代码展示

https://www.luogu.com.cn/paste/zx48ow5a


I - Two Melodies

非本校OJ题目传送门

题目分析

子段不一定连续且不相交问题,考虑一个 O ( n 2 ) O(n^2) O(n2) 的 DP。

设计状态 d p [ i ] [ j ] dp[i][j] dp[i][j],表示第一个序列结尾为 i i i,第二个序列结尾为 j j j 的最大的两个序列长度之和。显然有 d p [ i ] [ j ] = d p [ j ] [ i ] dp[i][j]=dp[j][i] dp[i][j]=dp[j][i],为了防止冲突,我们只枚举 i < j ii<j 的情况,因为当 i > j i>j i>j 时,我们难以保证第二个序列不与第一个相交。

如果单纯转移,我们还需枚举一维 k k k,即把 a j a_j aj 接在 a k a_k ak 后面。为了去掉这一维,我们用两个数组 m x m o d \mathrm{mxmod} mxmod m x n u m \mathrm{mxnum} mxnum 分别记录当 k ∈ [ 1 , i ) k\in[1,i) k[1,i) 时满足 a j a_j aj a k a_k ak 7 7 7 同余的最大的 d p [ i ] [ k ] dp[i][k] dp[i][k] 和满足 a b s ( a j − a k ) = 1 \mathrm{abs}(a_j-a_k)=1 abs(ajak)=1 的最大的 d p [ i ] [ k ] dp[i][k] dp[i][k],从而顺利实现转移。

边界条件: d p [ i ] [ j ] = d p [ i ] [ 0 ] + 1 dp[i][j]=dp[i][0]+1 dp[i][j]=dp[i][0]+1

转移方程: d p [ i ] [ j ] = max ⁡ ( m x m o d [ a j ] , m x n u m [ a j ± 1 ] ) + 1 dp[i][j]=\max(\mathrm{mxmod}[a_j],\mathrm{mxnum}[a_j\pm 1])+1 dp[i][j]=max(mxmod[aj],mxnum[aj±1])+1

注意在每次转移完后都要继续为下一次的转移更新数组 m x m o d \mathrm{mxmod} mxmod m x n u m \mathrm{mxnum} mxnum。注意语句 d p [ j ] [ i ] = d p [ i ] [ j ] dp[j][i]=dp[i][j] dp[j][i]=dp[i][j] 不可丢下。

时间复杂度为 O ( n 2 ) O(n^2) O(n2),实际上本题因为清空两个桶数组的原因复杂度会达到 O ( n × 1 0 5 ) O(n\times 10^5) O(n×105),但仍能通过本题,我也不知道为什么。

本题采用网络流的做法会更快,直接吊打 DP,但是笔者不会,此处不提。

代码展示

https://www.luogu.com.cn/paste/n95ohyo3

你可能感兴趣的:(题解,算法,数据结构)