Atcoder Grand Contest 003(A~F)
赛时打了 80 分钟,后来因为要处理一些私事就没再打,过掉了 ABC,推了 DE 没推出来,不能算很差,但也不算很好。
总结一下吧。
赛时
A 一眼题,统计四个方向是否出现过,如果相对的两个方向只出现了一个则不能走到,否则可以走到。
B 小贪心,还挂了两发……第一个思路是先尽量一起取相邻的两个值,取完后如果每个值还有剩余就再取单值,不过一眼假,比如出现【奇偶奇】的情况就不太对了。
正解就是先单取配对,取完后如果剩下一个值则和下一个值配对,最后输出总对数即可。
C 还挺妙。总结题意其实就是相邻三个数可以随便翻转任意次,但是要尽量少翻转相邻两个数。注意到翻转三个数的时候中间的数位置是不变的,只会调换两侧数的位置,即在翻转三个数的时候奇数位置和偶数位置是相对闭合的,奇数位之间可以任意调换位置,偶数位之间也可以任意调换位置,但是奇数位和偶数位不能互相调换。
所以我们可以先将原数组排序,看看有几个初始在奇数位置的数排序后在偶数位置,对于这些数,我们就需要通过一次翻转两个数的操作将他们位置的奇偶性改变,然后就可以通过三个数翻转将数组排序了。
所以我们统计一下原始数组位于奇数位置且排序后位于偶数位置的元素个数(将这些排完之后剩下的也就排完了),即为答案。
D 推了半天性质,不会,不会。
E 好像和循环关系很大,感觉想到了一个处理起来有点类似于 KMP 的做法,但是细节不会处理,复杂度好像可以被卡掉(
赛后
D - Anticube
D 题看了题解,感觉是一道数论相关的分讨好题。
首先立方数具有的一个性质是,每一种质因子的个数一定是三的倍数。
关于质因子有一个很广泛的性质是,对于一个数 \(x\),最多只有一个大于 \(\sqrt{x}\) 的质因子。
所以设题中 \(s\) 的上界为 \(S\),我们很容易想到分解每一个 \(s_i\) 然后比较,如果 \(s_i\) 存在一个大于 \(\sqrt{S}\) 的质因子,那么这个数显然不可能和其他数乘积凑成立方数——因为其他数最多也只有一个相同的质因子,不可能凑成三个;然后随便搞一下。但是这样单分解质因子的时间复杂度就是 \(O(n\sqrt{S})\) 了,显然是不对的。
可以考虑进一步扩展这个性质吗?对于一个数 \(x\),最多只有两个大于 \(\sqrt[3]{x}\) 的质因子。如果我们能让时间复杂度基于 \(O(n\sqrt[3]{S})\),显然就可以了。
怎么利用这个性质呢?首先考虑简化问题,先枚举 \([1,\sqrt[3]{S}]\),将每一个 \(s_i\) 的立方根因子干掉,保证每一种质因数的个数都在两个以内,并找到每一个 \(s_i\) 每一个立方根因子剩下的具体个数。然后我们开始进行分类讨论。
- 对于一个数 \(x\),如果它拥有一个大于 \(\sqrt{n}\) 的质因子,显然不会和其他任何数冲突。
- 除此之外,它还可能拥有一个或者两个大小在 \(\sqrt[3]{n}\) 和 \(\sqrt{n}\) 之间的质因子,那么显然,只有在这个范围内质因子大小相同,且个数分别为 \(1\) 个和 \(2\) 个的数才可能会冲突。所以假设 \(x\) 还有的两个在这个范围内的质因子大小不同,显然无法和其它数凑对;如果只有一个或者有两个大小相同的质因子,才可能可以凑对。
- 对于不存在 \(\sqrt[3]{n}\) 以上质因子的 \(s_i\),只会互相冲突。
于是我们就将他们分了个类,并且注意到,如果将每一个质因子的个数都取模 \(3\) 以后,产生冲突的数应该是两两对应的,即对于一个数 \(x\),如果我们将它的每一个质因子的个数都对于 \(3\) 取个差,就是会和它产生冲突的数。
那么计算贡献的方案就明了起来了。第一种数我们可以直接计入贡献;第三种则可以开一个 map,对于当前的 \(s_i\)(已经将质因子个数取模过的),考虑找到会和其产生冲突的数 \(x\),将 \(s_i\) 所在项加 \(1\) 后和 \(x\) 所在项取最大值即为这一对值对于答案的贡献;第二种则类似,含有两个不同大质因子时可以直接计入贡献;否则对于每一个大质因子分别开一个 map,或者用两个关键词查询 map 即可。
时间复杂度 \(O(n\sqrt[3]{n}+n\log n)\).
注意对于本来就是立方数的数,只能存在一个,需要特判。
E - Sequential operations on Sequence
E 正解跟场上想的很像。
首先注意到如果对于两个相邻的操作 \(q_i\) 和 \(q_{i+1}\),\(q_i>q_{i+1}\),那么 \(q_i\) 对于答案其实是无贡献的,完全可以被 \(q_{i+1}\) 完美替代。所以我们可以先用单调栈处理出一个单调递增的 \(q\) 数组,再考虑怎么做。
设最终变成的序列为 \(a\),对于单调递增数组的 \(q_i\) 和 \(q_{i+1}\),设 \(q_{i+1}=rq_i+s\),\(r,s\in N\),则 \([a_{q_{i}+1},a_{q_{i+1}}]\) 这一段的对于答案贡献显然是和 \(r\times[a_{1},a_{q_i}]+[a_{1},a_{s}]\) 相同的。这个性质就很有意思了。
如果我们已经处理完了 \([1,i]\) 询问的贡献,在处理 \(q_{i+1}\) 时,我们好像就可以将所有答案乘上 \(r\),再加上\([a_1,a_s]\) 的贡献。\([a_1,a_s]\) 的贡献又该怎么求?可以再考虑向前找到一个 \(j\) 使得 \(q_j<a_s\),且 \(q_{j+1}\ge a_s\) ,再取模、向前递归。这样做复杂度显然是对的,因为每次取模之后我们的余数必定至少减半,所以递归的时间复杂度只有 \(\log\),找 \(j\) 需要二分,也是一个 \(\log\)。一共只有两只 \(\log\),十分优秀。
不过我们发现如果这样做的话,我们很难在递归过程中快速计算贡献——这些贡献是复杂的,数据结构很难维护它们。不过我们注意到后面的询问用到的是前面的答案,将前面的贡献加到后面困难,那我们可以尝试将后面的询问挂在前面啊!
考虑倒序处理询问,每次询问向前不断递归,将子询问挂在前面的 \(q\) 上,作一个类似于离线差分的操作,最后统计答案即可。
tips:正着做不好转移,就可以考虑倒着做向前挂询问。
F - Fraction of Fractal
It is possible to traverse from any black cell to any other black cell by just visiting black cells.
一定要好好读题啊啊啊,\(0\) 级分形内一定只有一个联通块!!!
感觉应该是一道很经典的分形题目。
首先要明确的一点是,如果 \(k\) 级分形中某一行的最左边和最右边都是黑色格子,那么在 \(k+1\) 级分形中这两边本不相连的黑色联通块就可能会变得连通,我们可以定义该分形是【左右连通】的;同理,如果某一列的最上边和最下边都是黑色格子,我们定义该分形是【上下连通】的。
设 \(1\) 级分形中黑色格子的个数为 \(cnt\) 个,让我们来考虑两种简单的情况:
-
如果 \(1\) 级分形既不【左右连通】也不【上下连通】,那么 \(k\) 级分形中的连通块个数为 \(cnt^{k-1}\)。
-
如果 \(1\) 级分形既【左右连通】又【上下连通】,那么 \(k\) 级分形中的连通块个数一定为 \(1\)。
这两种情况的答案是显而易见的。
那么剩下的就只有【左右连通】和【上下连通】占其一的情况了。
两者处理方式相似,我们拿【左右连通】举例,注意此时已经含有【上下不连通】的隐含条件了。即对于大于 \(1\) 级的分形,每一分形行都是独立的。
我们设初始左右连通的连通块数为 \(tot\),初始左右连通的行数为 \(cmt\),\(k\) 级分形之后左右连通的块数为 \(s_k\),则显然有:
这很显然,由于每一分形行独立,对于原来左右连通的每一个连通块,在新一级分形中都会变成 \(cmt\) 个连通块。
那么我们设 \(k\) 级分形之后黑色连通块的个数为 \(ans_k\),则每一次分形显然都会将原来的连通块个数复制 \(cnt\) 份之后砍掉左右连通减去的块数。设 \(1\) 级分形中左右相邻的黑色格子个数为 \(pnt\),则有:
注意到 \(k\) 很大,于是我们将这些变量写进一个矩阵,快速转移即可。
tips:分形的题目可以考虑以分形级别作为 dp 阶段进行转移。