第二届全国大学生算法设计与编程挑战赛(春季赛)正式赛题解&比赛回顾
前言
很幸运地拿到了 rank 1!感谢主办方老板(
这次 rank 1 主要还是运气不错,第二次打 ACM 赛制就碰上了配合这么默契的队友,然后关键题都做得比较顺利。
比赛回顾
咕咕咕
题解
题解会尽量照顾到所有水平的选手,会很通俗易懂 =w=
如果我没更新记得私信/QQ催我!
Overall
题目编号 | A | B | C | D | E | F | G | H | I | J | K | L |
---|---|---|---|---|---|---|---|---|---|---|---|---|
思维难度 | 0 | 3 | 1 | 0 | 5 | 2 | 2 | 0 | 6 | 4 | ? | 0 |
实现难度 | 0 | 1 | 1 | 1 | 3 | 2 | 2 | 1 | 7 | 3 | ? | 0 |
所有难度均从 \(0\) 到 \(10\) 打分。
Problem A 智慧果
题面
已知序列 $a$:- \(a_1=1,a_2=2,a_3=3\)
- \(a_i=a_{i-1}a_{i-2}a_{i-3}+a_{i-1}+a_{i-2}+a_{i-3}\)
求 \(a_{1000}\) 对 \(100000\) 取模的值。
题解
暴力计算每一项对 $100000$ 取模的值即可。时间复杂度 \(O(n)\),其中 \(n\) 为项数。
Problem B Xanadu
题面
给定一个 $n\times n$ 的 $01$ 矩阵,和 $n$ 个点的图。你可以花费 $1$ 的代价将矩阵中的一个 $1$ 变成 $0$。操作完成后,记第 \(i\) 行从左到右第一个为 \(1\) 的位置为 \(j\),则在图上从 \(i\) 到 \(j\) 之间连一条有向边。
问至少要花费多少代价,才能让图上存在一条从 \(1\) 到 \(n\) 的路径,如果无法达成输出 \(-1\)。
\(n\leq 300\)。
题解
不难发现最后得到的一定是一棵基环树,因此如果有路径,必然存在一条无环的路径,即每个点仅经过一次。我们对于矩阵建图。假设第 \(i\) 行的第 \(j\) 个位置是该行第 \(k\) 个 \(1\),我们就从 \(i\) 到 \(j\) 建一条费用为 \(k-1\) 的边。
不难发现,最后得到的每条从 \(1\) 到 \(n\) 的路径的边权总和就是这个方案要花费的代价,因此直接在原图上跑最短路即可。
时间复杂度 \(O(n^2)\) 或 \(O(n^2\log n)\)。
Problem C 这是一道大难题
题面
给定一张图,求其必须包含给定一条边的最小生成树。\(n\leq 10^5,m\leq 2\times10^5\)。
题解
直接先加入这条边,然后跑 Kruskal 算法即可。正确性显然。
时间复杂度为 \(O(m\log m+n\alpha(n))\)。
Problem D zeal
题面
给定长度为 $n$ 的序列 $a$,$m$ 次求 $[l,r]$ 中出现 $k$ 次的元素数量。\(n,m,a_i\leq 4\times 10^4\)
题解
直接上莫队算法即可。时间复杂度 \(O(n\sqrt m)\)。
Problem E Alice 大战 Bob
题面
给定一个长度为 $n$ 的序列,有 $m$ 次询问。每次询问给定 \(l,r\),Alice 和 Bob 依次操作,每次操作可以将 \(l\) 加 \(1\) 或者 \(r\) 减 \(1\)。操作后 \([l,r]\) 内的数若单调不升或单调不降,操作者获胜。
\(n,m\leq 10^6\)。
题解
做法和 AGC002E 十分类似。先把所有已经单调不升或单调不降的区域求出。
然后把一步能走到这些区域的位置求出。
于是问题变成了 AGC002E,可以自行查阅该题题解。
时间复杂度为 \(O(n+m)\) 或 \(O(n+m\log n)\)。
Problem F 这是一道大水题
题面
给定 $n$ 个操作,每个操作为将 $[l,r]$ 的数加 $k$。\(m\) 次询问只执行 \(t\notin[l,r]\) 的操作后 \([1,n]\) 的和。
\(n,m\leq 10^6\)。
题解
注意到执行的操作对答案的贡献都是 $(r-l+1)\times k$。于是对所有操作记录其 \(l,r\) 和贡献,统计答案时统计所有 \(r\) 小于 \(t\) 和 \(l\) 大于 \(t\) 的操作贡献和即可,这个可以通过线段树简单实现。
时间复杂度 \(O((n+m)\log n)\)。
Problem G List it all
题面
给定 $n$ 个 $1\sim 9$ 的数字,问能组成的所有不同数的和,对 $10^9+7$ 取模。\(n\leq 2\times 10^6\)。
题解
所有数的和等于数的个数加上所有数的平均数。数的个数和可以通过组合数公式简单计算,这里不再赘述。
对于平均数,不难发现每一位的数的平均值都等于给定的所有数的平均值,设每位平均值为 \(k\),总平均值即 \(11\cdots1\times k\)。
Problem H 智慧数
题面
定义一个数 $x$ 是好的,当且仅当存在一个正整数 $y|x$,使得 $x\neq y$ 且 $xy$ 为完全平方数。求从小到大第 \(3000\) 个好数。
题解
对每个数暴力枚举因数检验即可。记答案为 \(n\),存在 \(O(n^2),O(n\sqrt n),O(n\log n)\) 的解法。
Problem I Imp
题面
给定一个长度为 $n$ 的 $01$ 串和 $m$。你可以翻转单个字符,或同时翻转前 \(m\) 的倍数个字符,代价均为 \(1\)。
问使得字符串前 \(n-m\) 个字符和后 \(n-m\) 个字符全部相等的最小代价。
\(n,m\leq 300\)。
题解
比较有趣的一题。- Case 1
如果 \(2(n-m)\leq n\),即两段字符不交的情况中,由于整体翻转仅有一个操作,枚举是否执行这个操作后,对于每对字符判断是否需要翻转即可。
时间复杂度 \(O(n)\)。
- Case 2
考虑进行转化,记 \(f_i=[a_i=a_{i+m}]\),则对字符串的操作可以转化为对 \(f_i\) 的操作,目标为让 \(f_i\) 的。
注意到操作的特点,我们将 \(f_i\) 每 \(m\) 个组成一行,共 \(\lceil\frac{n-m}{m}\rceil\) 行。
我们记行数为 \(N\),列数为 \(M\)。
操作可以转化成每行和每列的操作,即翻转每行,翻转每列最上面和最下面的一格,翻转每列连续的两格。
于是一个暴力产生了:枚举每行是否翻转后对整个矩阵求答案,时间复杂度为 \(O(2^M\text{poly}(n))\)。
然后我们发现我们还可以再写一个暴力:
假设我们已经把和前 \(i\) 行相关的所有操作做完了,第 \(i+1\) 行的状态为 \(S\) 的最小操作数为 \(f_{i,S}\),我们可以通过 dp 来求得答案,时间复杂度为 \(O(2^N\text{poly}(n))\)。
因此,我们可以根号分治这两种情况,时间复杂度为 \(O(2^{\min(N,M)}\text{poly}(n))=O(2^{\sqrt n}\text{poly}(n))\),可以通过。
Problem J 这是一道送分题
原题洛谷 P2466。
Problem K Chanllaging Problem
题面
咕咕咕题解
咕咕咕代码
咕咕咕Problem L 这是一道压轴题
题面
给定一个 $01$ 串,问删除一个极长相同字符子串后能得到最长的极长相同字符子串。\(|S|\leq 10^6\)
题解
显然得到的子串就是原来就有的串或者原来只隔一个极长相同字符子串的极长相同字符子串。找到极长相同字符子串后枚举即可。
时间复杂度 \(O(|S|)\)。