Atcoder Beginner Contest 272(A~E+G)
E 场上想麻烦了,调根号分治浪费了点时间;F 涉及后缀数组,还没有系统学;G 场上没来的及看,也沾点数学,估计场上也想不到(
不好,不好。
赛时
A 神笔数组求和;B 迷你模拟;C 分别找到奇数和偶数中最大的两个数,取最大的和即可。
D 题简单广搜,扩展时枚举一个坐标求出另一个坐标即可,注意不要忘记正负都可以扩展。
怎么还 WA 了两发呢?哦,没看见题目中走不到要输出 -1 啊。
E 疯狂看错题(md 下次做题看懂题意之后必须再读一遍验证一下),第一遍看成了单点加求序列 mex,想这不是 shabby 题,立马飞速码了一棵值域线段树,准备在上面进行二分了,写完发现没有操作可以读入,吃了一惊,然后发现是有规律的对每一个位置都单点加!
当时就稍微有点慌了,想了想发现只有当前值位于 \(0\) 到 \(n-1\) 之间的时候才可能对答案产生一下影响,而对于较小位置的数增长速度较慢,较大位置的数增长速度较快,所以想到了根号分治。
由于小于 \(\sqrt{n}\) 的数很少,所以我们可以对于每次操作将它们暴力加;大于 \(\sqrt{n}\) 的数最多只会待在 \(0\) 到 \(n-1\) 之间 \(\sqrt{n}\) 次操作,所以我们可以将它们提前挂在这些操作上。然后枚举每次操作处理即可。由于我们为了使得处理方便需要使得挂在每个节点上的数值有序,所以我们对于每次操作将这些数值排序,所以若还要优化复杂度可以将块长调大,大概可以达到 \(O(n\sqrt{n\log n})\) 左右的复杂度。
有一些细节需要处理,考场上由于心态崩掉罚了 114514 发时(悲
但实际上根本不需要这么麻烦,因为这道题有一个比 sqrt 更强的性质。注意到位于第 \(i\) 个位置上的数最多在 \(0\) 到 \(n-1\) 之间 \(\frac{n}{i}\) 次操作,而 \(\sum_{i=1}^{n}\frac{n}{i}=n\log n\) —— 没错,就是调和级数。
根据这个性质,我们可以把时间复杂度优化到 \(O(n\log n)\)。简单又好写。
小丑,有小丑。
F 推了半天,开始以为和最小表示法之类的东西有关系,简单写了下发现不对,又预感是后缀数组相关的题了,又想看看 G 但是没时间了。后来一看果真如此,那就先不补了,以后专题学习字符串的时候再补吧。
赛后
补了个 G。
G 一看有取模又想到了根号分治(md 这人魔怔了),但事实上没有什么性质可以让我们这么干。
那这题都有什么性质呢?
-
\(a_i\bmod M=a_j\bmod M\Rightarrow a_i\equiv a_j\Rightarrow (a_i-a_j)\ |\ M\)
-
对于一个合法的 \(M\),有超过一半的数同余 \(\Rightarrow\) 我们任意选择两个数,有至少 \(\frac{1}{4}\) 的概率同余。
-
对于一个大于 \(2\) 的质数 \(p_i\) 和一个合数 \(p_is\),如果模数 \(p_is\) 能够满足条件,则 \(p_i\) 也一定可以。
结合这些优良的性质,我们便首先可以设计出一个随机化算法。对于每次随机,我们可以随机两个下标 \(i,j\),将 \(|a_i-a_j|\) 求出后找到它的所有质因数,对于每个质因数 check 一遍整个数组,那么单次随机的时间复杂度就是 \(O(n\sqrt{A})\),其中 check 部分可以 \(O(n)\) 解决(可以先 \(O(n)\) 找到一个满足必要性的余数,再 \(O(n)\) 判断该余数的充分性)。随机十次正确率便有 \(95\%\) 左右了。
但是这毕竟是个随机化算法,有没有什么正经的算法呢?
我们还可以注意到一个性质:
- 对于长度为偶数的数组,如果存在模数解 \(M\),则一定存在两个相邻的 \(a\) 在模 \(M\) 意义下同余;对于长度为奇数的数组,则另存在一种只选奇数位置上的数的情况。
对于后者我们可以进行特殊判断,找到所有奇数位置上的相邻两个数之差的最大公因数,如果大于等于 \(3\) 则有解。
对于前者,我们可以处理出 \(\forall i\in [1,n-1),|a_i-a_{i+1}|\) 的所有不同的质因数。又由于 \(1e9\) 以内的数最多有 \(10\) 个左右不同的质因子,所以总质因子个数是 \(O(n)\) 级别的。处理完之后再将每个质因子 check 一遍即可,时间复杂度 \(O(n^2)\),有一个 \(10\) 左右的常数。(注意特殊处理 \(2\),可以将 \(2\) 变成 \(4\))
还是有些妙的。
启发
- 【解题】一定要多关注题目中的每一个条件,多找性质。
- 【trick】如果很难找到正确复杂度的做法可以考虑思考随机化错解的正确率,向随机化算法以及 hash 的方向想。
- 【赛时】不在能力范围内或者不擅长的题目类型一定要先跳过,尝试思考后面的题目。