AtCoder 简单题乱做
- APC001F XOR Tree
- ABC259H Yet Another Path Counting
- ABC258H Odd Steps
- ABC257G Prefix Concatenation
- ARC126D Pure Straight
- AGC019F Yes or No
- ARC121F Logical Operations on Tree
- ABC242H Random Painting
- ARC073F Many Moves
- AGC055D ABC Ultimatum
- ARC105F Lights Out on Connected Graph
- ARC146C Even XOR
- ARC147D Sets Scores
- ABC270G Sequence in mod P
- AGC013D Piling Up
- ARC108E Random IS
- ARC108F Paint Tree
- AGC001C Shorten Diameter
- ARC064F Rotated Palindromes
- ARC080E Young Maids
- ARC079F Namori Grundy
- ARC074F Lotus Leaves
- ARC072E Alice in linear land
- ARC070F HonestOrUnkind
- ARC069F Flags
- ARC078F Mole and Abandoned Mine
- ARC078E Awkward Response
- ARC077E guruguru
开个天坑……
另:真的是简单题!!1
APC001F XOR Tree
容易想到把每个点点权看成它到根的路径的权值异或和,但这样没啥用,因为一次修改还是会改很多个点。
考虑链的一些性质,其中有一条是有 \(len-2\) 个点度数为 \(2\),剩下 \(2\) 个点度数为 \(1\),考虑在这上面做文章。
一种想法是把每个点的点权设成与它相连的边的边权异或和,这样改一条链就只会改变两个端点了。
把所有点的点权拿出来,每次可以先把两个一样的删掉。因为边权 \(\le 15\),所以可以直接暴力统计。
对于剩下的有奇数个点有的点权,可以状压。设 \(f_S\) 表示有 \(S\) 中的数,要使得异或和为 \(0\) 的最少操作次数。
显然若 \(S\) 中的数异或和不是 \(0\) 就不可能变成 \(0\),否则下界就是 \(\operatorname{popcount}(S)-1\)。DP 的时候枚举一个异或和为 \(0\) 的子集进行转移。
Code:https://pastebin.ubuntu.com/p/xr2Bfbt62v/。
ABC259H Yet Another Path Counting
题意:
给一个 \(n\times n\) 的棋盘,每个格子有一个数 \(a_{i,j}\),规定只能向右和向下走,求 \(\sum\limits_{i,j}\sum\limits_{k,l}[a_{i,j}=a_{k,l}]\text{Path}((i,j),(k,l))\) 模 \(998244353\) 的结果,其中 \(\text{Path}((i,j),(k,l))\) 为按照上述规则从 \((i,j)\) 走到 \((k,l)\) 的方案数。
数据范围:\(1\le n\le 400,1\le a_{i,j}\le n^2\)。
对每一种数字考虑:
- 如果个数 \(\le n\),那么枚举两个颜色相同的点,用组合数算路径条数。因为 \(cnt_i\le n\),所以 \(\sum cnt_i^2\le n\sum cnt_i\);又因为 \(\sum cnt_i \le n^2\),所以 \(n\sum cnt_i\le n^3\)。因此这样做是 \(O(n^3)\) 的。
- 如果个数 \(> n\),那么对整个棋盘做一遍暴力 dp,容易发现这样做的次数不会超过 \(n\) 次。所以这样做也是 \(O(n^3)\) 的。
那么总复杂度就是 \(O(n^3)\) 的。
Code:https://pastebin.ubuntu.com/p/D2W5423GnR/。
ABC258H Odd Steps
题意:
求满足以下条件的序列 \(X\) 的数量模 \(998244353\) 的结果:
- \(X\) 的每一项都是奇数;
- \(X\) 每一项的和为 \(S\);
- \(X\) 的前缀和没有一项在 \(\{A_{1\dots n}\}\) 中。即设 \(Y_i=\sum\limits_{j=1}^i X_j\),那么 \(\forall 1\le i\le |X|,1\le j\le n,Y_i\ne A_j\)。
数据范围:\(1\le n\le 10^5,1\le A_1<A_2<\dots<A_n<S\le 10^{18}\)。
问题可以转化成在 \(1\sim S\) 中选出若干个数,使得排序后相邻两个数奇偶性不同,且 \(0\) 和 \(S\) 必须选。
一个比较显然的 dp 是设 \(f_{i,j}\),其中 \(j\in\{0,1\}\),表示在 \(0\sim i\) 中选数,选的最后一个数奇偶性是 \(j\) 的方案数。
转移可以直接考虑 \(i+1\) 选不选,复杂度是 \(O(S)\) 的。
发现这似乎不太好优化,因为转移的时候还和 \(i+1\) 的奇偶性有关。
那么考虑换一种设状态的方式,即设 \(f_{i,j}\),其中 \(j\in\{0,1\}\),表示在 \(0\sim i\) 中选数,选的最后一个数奇偶性是 \((i+j)\bmod 2\) 的方案数。
把式子写出来发现对于可以选 \(i+1\) 的连续的段,可以用矩乘优化。而这 \(n\) 个数把序列分成了 \(n+1\) 段,每一段都跑一遍矩乘就行了。复杂度 \(O(n\log S)\)。
Code:https://pastebin.ubuntu.com/p/44Rwd4KZmY/。
ABC257G Prefix Concatenation
题意:
给定两个字符串 \(S\) 和 \(T\),问最少用多少个 \(S\) 的前缀相接能够拼出 \(T\),或者输出无解。
数据范围:\(1\le |S|,|T|\le 5\times 10^5\)。
考虑 dp。
如果从前缀入手会发现不好优化,那么就考虑以后缀设计状态。
设 \(f_i\) 表示拼凑出 \(T_{i\dots n}\) 所需的最少次数。
不难发现一定是从一段区间的最小值转移过来,那么可以利用哈希二分出能转移的最右点,线段树优化 dp 即可。
Code:https://pastebin.ubuntu.com/p/htsznFXq3V/。
ARC126D Pure Straight
题意:
给定一个长度为 \(n\)、值域为 \([1,K]\) 的序列 \(A\),每次可以交换相邻两个数,问最少多少次使得序列中存在一个 \(1,2,\dots,K\) 的子串。
数据范围:\(2\le K\le 16,K\le n\le 200\)。
考虑如果我们已经知道要把一些数放到一起,怎么做才能让操作次数最少。根据小学奥数知识不难得出一定是全部移到中位数那里。因为一定要 \(1\sim K\) 顺序排列,所以操作次数还要加上逆序对数。
枚举最终中位数 \(mid\) 的位置,那么一定是有 \(\lfloor\frac{K}{2}\rfloor\) 的数从 \(mid\) 左边过来,\(\lceil\frac{K}{2}\rceil\) 的数从 \(mid\) 右边(包括 \(mid\))过来。因为 \(K\le 16\),所以我们可以暴力枚举哪些数从左边过来、哪些数从右边过来。同时求出 \(mid\) 左右最近的数值为某个数的位置。
利用一开始的结论暴力计算次数,取最小值即可。
Code:https://pastebin.ubuntu.com/p/CkzGnJ8KPB/。
AGC019F Yes or No
设 \(n'\) 为剩余答案为 Yes 的数量,\(m'\) 为剩余答案为 No 的数量。
不难发现,当前给出的答案一定是 \(n'\) 和 \(m'\) 中较大的那一个。
一开始肯定有一个很显然的 dp:设 \(f_{i,j}\) 表示剩下的答案是 Yes 的有 \(i\) 个、答案是 No 的有 \(j\) 个,转移方程不难得出:
其中 \(\frac{\max(i,j)}{i+j}\) 是这一题答对的概率。
显然这是 \(O(n^2)\) 的。
换一种思路,把问题转换到格路上来:即横轴为答案是 Yes 的个数、纵轴为答案是 No 的个数,那么答案和我们的回答就可以看成是一条只能向下和向左走、从 \((n,m)\) 走到 \((0,0)\) 的路径。
不失一般性的假设 \(n\ge m\)。
不难发现,在回答的路径没有接触到直线 \(y=x\) 时,我们一定只会选 Yes(因为此时肯定 \(n'>m'\)),贡献是 \(\max(n,m)\),因为这 \(\max(n,m)\) 个题一定会答对。
考虑在直线 \(y=x\) 上的点,它们的意义是剩下的答案 Yes 与 No 的数量相等,那么我们只能随便蒙一个,有 \(\frac{1}{2}\) 的概率蒙对。而且走完这一步后下一步一定还会回到 \(y=x\) 上(因为走完这一步后 \(n'\) 与 \(m'\) 就不相等了)。因此直线 \(y=x\) 的额外贡献就是 \(\dfrac{1}{2}\sum\limits_{i=1}^m\dfrac{\binom{n-i+m-i}{n-i}\binom{2i}{i}}{\binom{n+m}{n}}\),即路径经过这个点的概率。
那么总的答案就是 \(\max(n,m)+\dfrac{1}{2}\sum\limits_{i=1}^m\dfrac{\binom{n-i+m-i}{n-i}\binom{2i}{i}}{\binom{n+m}{n}}\)。
Code:https://pastebin.ubuntu.com/p/Z298mgVY3f/。
ARC121F Logical Operations on Tree
题意:
给定一棵 \(n\) 个点的树,要往每个点上写 0 或 1,每条边上写 and 或 or。可以每次选择一条边,把这条边两端的点缩成一个点,并将上面的数改成原来点的 and 或者or,若最终可以缩成一个 1,则填写方案是合法的。
求合法方案数,对 \(998244353\)取模。
数据范围:\(2\le n \le 10^5\)。
萌萌题(雾
一个关键结论:我们肯定是先缩完所有的 and 边,再缩 or 边。
证明考虑交换相邻两个 and 和 or,发现把 and 放在 or 前面肯定不劣。具体读者自证不难。
有了这个结论后,显然最后能缩成 1 的充要条件是至少存在一个 and 边构成的连通块,里面的点填的全是 1。
那么可以树形 dp:设 \(f_{u,0/1,0/1}\) 表示 \(u\) 子树内,\(u\) 所在的 and 边构成的连通块里面的点是否全为 1,以及 \(u\) 子树内是否有全 1 的 and 边构成的连通块。转移枚举子树情况即可。
复杂度 \(O(n)\)。
Code:https://pastebin.ubuntu.com/p/RhPRP3hZk7/。
ABC242H Random Painting
题意:
给出 \(m\) 个区间 \([l_i,r_i]\),每次随机选择一个区间将区间内的数涂黑,问期望多少次能把 \(1\sim n\) 的所有位置都涂黑。保证有解。
数据范围:\(1\le n,m\le400,1\le l_i\le r_i\le n\)。
考虑 min-max 容斥:
- 如果是求 \(S\) 中的第 \(k\) 大,那么 \(\max_k(S)=\sum\limits_{\varnothing\ne T⊆ S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min(T)\)。
- 特别的,当 \(k=1\) 时,有 \(\max(S)=\sum\limits_{\varnothing\ne T⊆ S}(-1)^{|T|-1}\min(T)\)。
- min-max 容斥在期望意义下也成立。
那么我们只要求出所有集合期望有元素被涂黑的最早时间就行了。
考虑 dp:设 \(f_{i,j}\) 表示集合里最后一个元素是 \(i\),有 \(j\) 个区间覆盖这个集合的容斥系数之和。
转移考虑 \(f_{i,j}\to f_{k,l}\),那么不难发现 \(l=j+cnt_k-cnt_{i,k}\),其中 \(cnt_k\) 表示覆盖了 \(k\) 的区间数,\(cnt_{i,k}\) 表示同时覆盖了 \(i\) 和 \(k\) 的区间数,这个可以通过容斥得出。
最后求答案就是 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m f_{i,j}\times\frac{m}{j}\),因为在 \(m\) 个元素中选到 \(j\) 个元素中的任意一个的期望时间是 \(\frac{m}{j}\)。
Code:https://atcoder.jp/contests/abc242/submissions/33240625。
ARC073F Many Moves
设 \(f_{i,j}\) 表示有一个棋子在 \(x_i\),另一个棋子在 \(j\) 的最少移动步数。
转移有 \(f_{i-1,j}+|x_i-x_{i-1}|\to f_{i,j}\)。
还需要对于 \(f_{i,x_{i-1}}\) 特殊考虑,因为这个时候可以移动另一枚棋子。即 \(f_{i,x_{i-1}}=\min\{f_{i-1,j}+|x_i-j|\}\),可以分类讨论拆掉绝对值。
用线段树维护这个过程就行。
Code:https://pastebin.ubuntu.com/p/7Gh75jf8mk/。
AGC055D ABC Ultimatum
题意:
定义一个长度为 \(3n\) 的字符串 \(T\) 是好的,当且仅当它由 \(n\) 个
A
、\(n\) 个B
、\(n\) 个C
构成,且可以分成 \(n\) 个子序列,每个子序列满足其为ABC
、BCA
或CAB
。给一个长度为 \(3n\) 的字符串 \(S\),\(S_i\in\{\texttt{A,B,C,?}\}\)。问有多少种把
?
替换成A
、B
或C
的方法,使得 \(S\) 是好的。答案对 \(998244353\) 取模。数据范围:\(1\le n\le 15\)。
神仙题。
关键性质:
设 \(f_{\texttt{A/B/C}}=\max\limits_{i=1}^n\{\sum\limits_{j=1}^i([S_{j}=next(\texttt{A/B/C})]-[S_j=\texttt{A/B/C}])\}\),其中 \(next(\texttt{A/B/C})=\texttt{B/C/A}\)。
那么序列 \(S\) 是好的的充要条件为 \(f_{\texttt{A}}+f_{\texttt{B}}+f_{\texttt{C}}\le n\)。
考虑证明:
必要性:
- 每一个合法的子序列都包含恰好两个 \((d,next_d)\) 的顺序对。
- 考虑 \(f_{\texttt{A}}\),加入一个
ABC
或CAB
时某些前缀B
的个数减去前缀A
的个数会减少 \(1\),加入一个BCA
时某些前缀B
的个数减去前缀A
的个数会增加 \(1\),因此 \(f_{\texttt{A}}\le\)BCA
的出现次数。同理经过推导后可以得出 \(f_{\texttt{A}}+f_{\texttt{B}}+f_{\texttt{C}}\le n\)。必要性:
- 考虑如下构造:将第 \(i \in[1,n]\) 个
A
、\(i + f_{\texttt{A}}\) 个B
和第 \(i + f_\texttt{A}+ f_\texttt{B}\) 个C
组成一个子序列(后两者若大于 \(n\) 再减去 \(n\))。- 显然匹配的这些位置互不相同,而根据 \(f_{\texttt{A/B/C}}\) 的定义有,如果我们把 \(S\) 重复写三遍变成 \(S′\),那么第 \(i\) 个
A
的位置必然前于第 \(i + f_\texttt{A}\) 个B
的位置,前于第 \(i + f_\texttt{A}+ f_\texttt{B}\) 个C
的位置,前于第 \(i + f_\texttt{A}+ f_\texttt{B}+ f_\texttt{C}\) 个A
的位置(此处均指在 \(S′\)上的位置,不需要减 \(n\))。- 而根据条件可知,第 \(i + f_\texttt{A}+ f_\texttt{B}+ f_\texttt{C}\) 个
A
的位置前于第 \(i+n\) 个A
的位置。所以我们钦定的三个位置刚好顺着组成了ABC
,对应到序列上也就是ABC
、BCA
、CAB
的一种。
然后就不难有一个 \(\mathcal{O}(n^6)\) 的 dp:设 \(f_{i,a,b,fa,fb,fc}\) 表示前 \(i\) 个数,A
有 \(a\) 个,B
有 \(b\) 个,C
有 \(c\) 个,当前 \(f_\texttt{A}=fa\)、\(f_\texttt{B}=fb\)、\(f_\texttt{C}=fc\) 的方案数。转移枚举当前填什么就行。
Code:https://paste.ubuntu.com/p/8G8dgktNrc/。
ARC105F Lights Out on Connected Graph
题意:
给一个 \(N\) 点 \(M\) 边的无向图 \(G\),每条边都可以是红色或蓝色,初始全为红色,计数有多少种将 \(G\) 移去一些边成为 \(G′\) 的方案,满足以下条件:
- \(G′\) 连通;
- 每次操作选择一个点,将所有和这个点相连的边的颜色反转,要求可以通过若干次操作将所有边变蓝。
答案对 \(998244353\) 取模。
数据范围:\(N \le 17,N − 1 \le M \le\frac{N(N − 1)}{2}\)。
由于操作的点之间不能有边,不操作的点之间也不能有边,那么原图一定是一张二分图。
数据范围很小,考虑状压 DP。
首先算出 \(cnt_S\) 表示集合 \(S\) 内的点的导出子图的边数。
设 \(f_S\) 表示集合 \(S\) 内的点构成二分图的方案数(不要求连通),\(g_S\) 表示集合 \(S\) 内的点构成连通的二分图的方案数(为方便计算,二分图两边交换算两种方案,最后输出时再除掉)。
那么有:
关于求 \(g_S\),可以枚举 \(\text{lowbit}(S)\) 所在的一边的点,然后进行容斥,即:
复杂度 \(\mathcal{O}(3^N)\)。
Code:https://paste.ubuntu.com/p/zzy3pPxhyv/。
ARC146C Even XOR
题意:
问有多少个集合 \(S\) 满足:
- 其中每个元素大小都在 \(0\sim 2^n-1\) 之间;
- 对于 \(S\) 的每一个大小为偶数的子集 \(T\),\(T\) 的异或和不为 \(0\)。
答案对 \(998244353\) 取模。
数据范围:\(1\le n\le 2\times 10^5\)。
对于这道题,我们需要发现一些神奇的性质才能够解决。
考虑如果我们已经有大小为 \(i-1\) 的满足条件的集合,那么我们应该如何加入元素才能使得它依然满足条件?
我们将它的一个大小为奇数的集合拿出来,设它的异或和为 \(x\),那么显然不能插入 \(x\)。
结论:所有大小为奇数的集合异或和都不同。
证明:考虑两个异或和相同的大小为奇数的集合,把它们并起来,去掉出现次数为 \(2\) 的元素,那么剩下的元素一定有偶数个,并且异或和为 \(0\)。所以这个集合不满足条件,与假设矛盾。
所以,我们可以插入的数的数量就是 \(2^n-2^{i-2}\),其中 \(2^{i-2}\) 为大小为 \(i-1\) 的集合中大小为奇数的子集数量。
那么就有一个显然的 dp:设 \(f_i\) 表示大小为 \(i\) 的满足条件的集合数量。
则 \(f_0=1,f_1=2^n,f_i=\frac{f_{i-1}(2^n-2^{i-2})}{i}\)。除以 \(i\) 是因为不考虑插入的顺序。
从转移式中不难看出,满足条件的集合大小一定不会超过 \(n+1\)。
Code:https://pastebin.ubuntu.com/p/HKhWjTyjvh/。
ARC147D Sets Scores
在对一个问题没有什么思路的时候,考虑加强题目的限制,再对其扩展。
本题中,我们先假设已经确定了每相邻两个集合中只出现在一个里的数,那么我们只要确定了 \(S_1\),就可以确定所有的 \(S_{1\dots m}\)。
发现计算分数的式子是 \(\prod\),可以对每一种数单独考虑。其实我们只需要关心每种数是否出现在 \(S_1\) 中,设当它出现在 \(S_1\) 中时它在所有集合中的出现次数为 \(a_i\),那么当它不出现在 \(S_1\) 中时它在所有集合中的出现次数就是 \(n-a_i\)。因为如果它出现在 \(S_1\) 中时没有出现在某个集合中,那么当它不出现在 \(S_1\) 中时就肯定会出现。所以这部分每个数的贡献都是 \(n\),所有数贡献的乘积就是 \(n^m\)。
然后再考虑放开之前的限制,「每相邻两个集合中只出现在一个里的数」是一个长度为 \(n-1\) 的序列,总共有 \(m^{n-1}\) 种。
所以总的答案就是 \(n^mm^{n-1}\)。
我觉得应该不要代码……
ABC270G Sequence in mod P
把答案的式子写出来,其实就是要求满足 \(A^iS+A^{i-1}B+A^{i-2}B+\cdots+AB+B\equiv G\pmod P\) 的最小的 \(i\)。
当 \(B=0\) 的时候就是 BSGS 模板,考虑在加入了 \(B\) 之后还是按照一样的套路,设阈值 \(M=\sqrt P\),然后预处理 \(0\sim M\) 的值存入哈希表,其它的暴力每次跳 \(M\) 的大小。
那么最后的式子也就形如:
其中 \(x\) 是某个 \(M\) 的倍数。
移项后可得:
这样我们的思路就很明了了!
左右都可以递推得出来!
代码:https://pastebin.ubuntu.com/p/9Ctt5wdZZ4/。
AGC013D Piling Up
首先有一个显而易见的 DP:设 \(f_{i,j}\) 表示已经进行了 \(i\) 次操作,还剩下 \(j\) 个黑球的颜色序列数。转移的时候由于球的总数不变,所以只需要关心黑球 / 白球的有无,讨论四中情况即可。
但是这样会导致算重,因为相同的颜色序列一开始可能会有不同的黑球数。
那么考虑去重,我们只统计途中黑球的最小值刚好为 \(0\) 的那一次操作序列。
可以在 dp 式子里再加一维,同时也可以直接用有 \(n\) 的球的答案减去有 \(n-1\) 个球的答案。
为什么呢?这是因为如果途中黑球最小值不是 \(0\),那么把一开始的黑球数减去 \(1\) 该方案仍然可行。所以所有中间算重的操作序列最后都会被减掉,只会留下一个。
代码很好写:https://pastebin.ubuntu.com/p/DfWjCQ6YNp/。
ARC108E Random IS
区间满足可合并性,考虑区间 DP。
先在序列开头补上 \(a_0=0\),结尾补上 \(a_{n+1}=n+1\)。
设 \(f_{i,j}\) 表示选了 \(a_i\) 和 \(a_j\),在区间 \([i+1,j-1]\) 中选择若干个数的期望数量。
设 \(cnt_{i,j}=\sum\limits_{k=i+1}^{j-1}[a_i<a_k<a_j]\),转移有
倒序枚举 \(l\),然后正序枚举 \(r\),维护 \(n+2\) 个树状数组,分别维护 \(cnt\)、\(f_{i,*}\) 和 \(f_{*,j}\)。
时间复杂度 \(\mathcal{O}(n^2\log n)\)。
代码:https://pastebin.ubuntu.com/p/hj8PnSFN7w/。
ARC108F Paint Tree
首先拿出直径的两个端点 \(L,R\)。
如果这两个点同色,那么贡献就是直径的长度 \(D\),方案数为 \(2^{n-2}\times 2=2^{n-1}\)。
否则,不妨设 \(L\) 染成了白色,\(R\) 染成了黑色,最后方案数 \(\times 2\) 即可。
由直径的性质可知,一定有一个白点到 \(L\) 的距离为 \(x\),一定有一个黑点到 \(R\) 的距离为 \(y\)。
设 \(p_i\) 为点 \(i\) 到 \(L\) 的距离,\(q_i\) 为点 \(i\) 到 \(R\) 的距离。那么一种染色方案的贡献就相当于:每个点从 \(p_i\) 和 \(q_i\) 中选择一个出来,选择的数中的最大值就是贡献。
枚举 \(x\),考虑答案 \(\le x\) 的选择方案数。不难发现如果 \(\exist i,\min(p_i,q_i)>x\),那么方案数为 \(0\)。否则设 \(cnt\) 为 \(\max(p_i,q_i)\le x\) 的 \(i\) 的数量,方案数就为 \(2^{cnt}\)。
实现的时候可以用差分算出答案 \(=x\) 的方案数。
代码:https://pastebin.ubuntu.com/p/kbwhDjPjyh/。
AGC001C Shorten Diameter
数据范围很小,考虑枚举。
枚举直径的中点 / 中间的那条边,然后统计距离它 \(\le \frac{k}{2}\) 的点的数量。
不难发现这样肯定是对的,因为统计非直径中点的时候肯定不优。
这种直接枚举的题目考虑枚举到无效信息是否不比答案优,如果是的就直接枚举得了。
代码:https://pastebin.ubuntu.com/p/Nk47ZGr6Cf/。
ARC064F Rotated Palindromes
如果一个序列满足条件,那么它肯定有至少一个循环移位是回文的。
直接统计不太好做,考虑对每一个回文串计算它循环移位能得到多少个不同的串。
*看到循环移位,需要想到周期!!!
枚举最小周期 \(x\),那么 \(x\) 肯定是 \(n\) 的一个约数。考虑容斥减掉还有比 \(x\) 小的长度的周期的数量。
即记 \(cnt_x\) 表示最小周期为 \(x\) 的字符串数量,那么 \(cnt_x=k^{\lceil\frac{x}{2}\rceil}-\sum\limits_{y|x}cnt_y\)。
接下来考虑循环移位能得到的串的数量。如果循环节是奇数,那么把整个循环节挪到后面去都不会算重,贡献为 \(cnt_x\times x\);否则如果循环节是偶数,就只能把前一半挪到后面,因为再挪的话就会算重,所以贡献为 \(cnt_x\times \frac{x}{2}\)。
代码:https://pastebin.ubuntu.com/p/dVytf7fHWM/。
ARC080E Young Maids
对于这种最小化字典序的问题,考虑 fix 一段前缀,在这个基础上去考虑问题。
将操作反过来考虑,容易发现可以把这个操作和括号序列类比,每次只能取当前最外层的括号。
那么我们就可以对于每段区间找到可选择的所有括号对中字典序最小的,也就是在奇偶性和左端点相同的点中找一个值最小的,再在这个点右边找到一个奇偶性和右端点相同的值最小的点,那么我们这次操作就选择这两个点作为一对匹配的括号,不妨设这两个点为 \(x,y\)。
这两个点会将原区间分成三段,每段都是子问题,可以接着做。
用优先队列维护这个过程,每次取出 \(a_x\) 最小的候选区间即可。
代码:https://pastebin.ubuntu.com/p/YGq6RBp78r/。
ARC079F Namori Grundy
首先,图肯定是一个基环外向树。
其次,这个条件等价于每个点的权值是它的出边的点的权值的 \(\text{MEX}\)。
那么对于不在环上的点,我们可以通过叶子节点权值一定是 \(1\) 来从下往上递推得出它的权值。
对于环上的点,我们考虑先把它们的权值设为只考虑非环节点时的权值。
然后对于一条边 \((u,v)\),如果 \(a_u=a_v\),我们肯定需要调整,即将 \(a_u\leftarrow a_u+1\),然后对于 \(u\) 的前驱继续进行调整。
那么可以得出结论:当且仅当环长度是奇数且环上所有点权值相等的时候无解。因为这个时候 \(+1\) 操作会死循环。
代码:https://pastebin.ubuntu.com/p/mC3sXTysHZ/。
ARC074F Lotus Leaves
一眼最小割,关键是怎么建图。
建两排点分别表示行和列。
对于每一个 o
,将它对应的行和列之间连流量为 \(1\) 的双向边。对于 S
,将源点和它对应的行和列连流量为 \(\infty\) 的单向边。对于 T
,将它对应的行和列向汇点连流量为 \(\infty\) 的单向边。跑一遍最大流即可。
这是因为最小割的本质是和源点相连的点分成一组,和汇点相连的点分成另一组,其它的点无所谓。两个组之间是不连通的。
这题中,这样建图就保证了从 S
一定不能到 T
,因为它们的行列都不能互相到达。
代码:https://pastebin.ubuntu.com/p/VFksYqhyzB/。
ARC072E Alice in linear land
先求出每个前缀操作之后到的位置 \(b_i\)。
那么一次修改操作就相当于可以到达位置 \(0\sim b_{i-1}\),那么当且仅当这些位置在经过 \([i+1,n]\) 这些操作之后都能到达终点才输出 NO
。
我们可以把初始距离和经过一些操作后的距离看成一个函数关系,在这个函数上分析性质。
一直在想维护拐点之类的黑科技,但是一直没有突破,不好维护整个函数的性质。
但其实我们并不关心函数具体的样子,我们只关心它最小的不为 \(0\) 的位置(即最长的前缀 \(0\) 的长度)。
设 \(mn_i\) 为操作完 \([i,n]\) 后离终点的距离不为 \(0\) 的最小初始距离。
那么分类讨论一下:
- 若 \(mn_{i+1}\le \frac{a_i}{2}\),那么 \(mn_i=mn_{i+1}\),因为这个时候不能行动。
- 若 \(mn_{i+1}>\frac{a_i}{2}\),那么 \(mn_i=mn_{i+1}+a_i\)。
证明考虑反证法,即如果有一距离 \(x<mn_i\) 在操作之后不能到达终点,那么考虑它是从哪一个位置转移过来,分析过后会产生矛盾。
所以,如果 \(b_{i-1}<mn_{i+1}\) 就输出 NO
,否则输出 YES
。
代码:https://pastebin.ubuntu.com/p/HtCjQh9MFY/。
ARC070F HonestOrUnkind
一道很神奇的题目。
首先,如果 \(a\le b\) 则无解,因为这个时候不友好的人可以都假扮诚实的人,这个时候无法分辨。
剩下的就都是 \(a>b\) 的情况,我们可以类似摩尔投票那样,每次选择两个数,至少消除一个不友好的人。
考虑对于两个人 \(x,y\),如果我们询问 ? x y
返回了 N
,那么 \(x\) 和 \(y\) 中至少有一个是不友好的人。
那么我们用一个栈来维护这个过程。具体的,从小到大枚举 \(i\),如果栈为空就直接将 \(i\) 加入栈中;否则每次询问栈顶元素 \(x\):新加的元素 \(i\) 是否友好,如果返回 N
就将 \(x\) 弹出栈,否则就将 \(i\) 压入栈。
这样做完 \(n\) 轮之后,栈顶元素一定是诚实的人,再询问一遍所有的人的情况即可。询问数 \(2n-1\)。
考虑证明这种做法的正确性:
- 因为我们每次都会至少消除一个不友好的人,且每个时刻都保证了诚实的人的数量大于不友好的人的数量,所以最后栈中诚实的人肯定比不友好的人多。
- 如果栈顶是不友好的人,那么它肯定会被前一个诚实的人消除。这是因为栈中始终保证了诚实的人会在不友好的人的前面,否则就可以进行消除操作。
代码很好写:https://pastebin.ubuntu.com/p/njd6RbpGy2/。
ARC069F Flags
最大值最小,明示二分。
二分最大的最小距离 \(x\),那么对于每个点,都要求如果选了它,那么离它距离 \(<x\) 的点都不能选。
我们把所有点拿出来按坐标从小到大排序,记录 \((id,ty)\) 表示它是第 \(id\) 个标志的第 \(ty(=0/1)\) 种选择。
那么就相当于,对于每个点,向它左右距离小于 \(x\) 的所有点连边。同时每个点向它这个标志的另一种选择的点连边,表示这个点不能选择的时候就需要选另一个点。
暴力建图是 \(\mathcal{O}(n^2)\) 的。容易发现我们连边的实际上是一段区间,可以使用线段树优化连边做到 \(\mathcal{O}(n\log n)\)。
判定是否可行的话,直接判断每个标志的两种选择是否在同一个强连通分量里面。
后来发现这有点类似 2-SAT……
代码:https://pastebin.ubuntu.com/p/wgmdZc2brz/。
ARC078F Mole and Abandoned Mine
考虑图最终的形态,肯定是随便拿一条 \(1\to n\) 的路径,把路径上的边全部去掉,会形成若干个连通块,每个连通块的根分别对应路径上的一个点。
发现数据范围很小,考虑状压 DP。
设 \(f_{s,i}\) 表示已经选完了集合 \(s\) 中的所有点,当前 \(1\to i\) 的路径只有一条,能保留的边权的最大和是多少。
转移枚举下一个点 \(j\),或者枚举 \(i\) 所在连通块内的点,这个点集内部的所有边都可以保留(这个可以预处理)。
代码:https://pastebin.ubuntu.com/p/mCXgSwpZ96/。
ARC078E Awkward Response
不是很难的交互。
先询问一遍 1000000000
判断掉所有形如 10...0
的情况。之后可以问若干个 9
确定 0
的个数。
接下来多次询问 10...0
来求出位数。对于每一位直接二分。
注意一些实现细节。
代码:https://pastebin.ubuntu.com/p/Mds4YXgd5D/。
ARC077E guruguru
考虑每一轮移动时,理想亮度在每个位置的时候所需要的最小步数。
设起点为 \(l\),终点为 \(r\),分类讨论:
- \(l=r\),无论理想亮度是什么贡献都是 \(0\)。
- \(l<r\),\(1\sim l\) 和 \(r+1\sim n\) 的贡献都是 \(r-l\),\(l+1\sim r\) 的贡献是首项为 \(r-l\)、公差为 \(-1\) 的等差数列。特判 \(l=1\) 的情况。
- \(l>r\),\(1\sim r\) 的贡献是首项为 \(r\)、公差为 \(-1\) 的等差数列,\(r+1\sim l+1\) 的贡献都是 \(n-l+r\),\(l+2\sim n\) 的贡献是首项为 \(n-l+r-1\)、公差为 \(-1\) 的等差数列。特判 \(r=1\) 的情况。
对于每种情况,都可以用二阶差分表示出来。然后做两遍前缀和就行了。