AtCoder 比赛记录
ARC 140
打得很烂。Rank 590,Performance 1696。
D - One to One
每个点都有恰好一个出边,所以这是一个外向基环森林。因此连通块数就等于环的个数,我们只需要求出所有方案中环的个数的总和。直接算比较难办,考虑算每个环对答案的贡献。
首先,假如忽略掉 \(A_i=-1\) 的连通块,剩下的环是一定存在的,可以预先加到答案里。然后,观察到任意一个点数为 \(k\) 的、由 \(A_i=-1\) 的连通块组成的环,都会出现在 \(n^{c-k}\) 种方案里,其中 \(c\) 是 \(A_i=-1\) 的 \(i\) 的个数。接下来就是要计算出,对于所有 \(k=1,2,\dots,c\),点数为 \(k\) 的环有多少个。
假如我们任取 \(k\) 个 \(A_i=-1\) 的 \(i\),并设它们所在的连通块大小为 \(s_1,s_2,\dots,s_k\),那么这 \(k\) 个连通块可以组成 \((k-1)!\prod_{i=1}^k s_i\) 种不同的环,且这些环上都恰好有 \(k\) 个 \(A_i=-1\) 的位置。所以,可以直接 DP(或者分治 FFT)算出环的个数,并求出答案。
时间复杂度 \(\mathcal{O}(n^2)\)(DP)或者 \(\mathcal{O}(n\log^2 n)\)(分治 FFT)。
ARC 141
Rank 164,Performance 2313。
A - Periodic Number
我做麻烦了。首先,假如 \(N\ge 99\),一个显然的答案是 \(99\dots 9\)。枚举 \(N\) 的每个前缀 \(N'\),只需要检查 \(N'\) 循环拼接和 \(N'-1\) 循环拼接是否合法即可。
ABC 260
Rank 167,Performance 2305。
G - Scalene Triangle Area
在 \((1,1)\) 处执行一次区域加,会形成如下图形:
++++++
++++00
++0000
000000
二维差分后,得到:
+00000-0
0000-0+0
00-0+000
-0+00000
相当于在 \((u,v)\) 处单点加一,并在两条斜率为 \(\frac{1}{2}\) 的线段上 \(\pm 1\)。线段加减可以再进行一次差分:先将线段的开始位置 \(\pm 1\),并将线段的结束位置后面 \(\mp 1\)。所有操作执行完后,设 \(S_{i,j}\) 表示当前 \((i,j)\) 位置的值,我们从小到大枚举 \(j\),令 \(S_{i,j}\gets S_{i,j}+S_{i+1,j-2}\),也就是斜着做一次前缀和。
最终再做一次二维前缀和即可。时间复杂度 \(O(N^2+Q)\)。
AGC 058
Rank 106,Performance 2722。
A - Make it Zigzag
喜报:我的做法被我自己叉了!
以下是正确做法:
考虑第一个不合法的奇数位置 \(i\),那么有 \(P_i>P_{i+1}\)。
- 若 \(P_i>P_{i+2}\),则交换 \(P_i,P_{i+1}\);
- 否则,交换 \(P_{i+1},P_{i+2}\)。
偶数位置同理。每次操作会使得第一个不合法的位置至少后移两位,因此操作次数 \(\le N\)。
B - Adjacent Chmax
对于每个位置 \(i\),设
现在,问题转化成了:对于每个 \(i\),你可以用 \(P_i\) 覆盖 \((l_i,r_i)\) 中的一段子区间 \([L_i,R_i]\),且你需要保证 \(\forall i>1,L_i=R_{i-1}+1\)。问最终能得到多少种不同的序列。
设 \(f_{i,j}\) 表示用 \(P_{1\dots i}\) 覆盖长度为 \(j\) 的满足上述条件的序列,能得到多少种不同的序列。直接转移即可,时间复杂度 \(O(N^2)\)。
D - Yet Another ABC String
考虑容斥。将 \(S\) 划分为极长的 ABCABC...
的子串,设其中有 \(k\) 个长度 \(\ge 3\) 的段,令其容斥系数为 \((-1)^k\)。
枚举 \(k\),我们要计算满足上述条件的字符串个数。若 \(S\) 开头的段长度 \(\ge 3\),那么 \(S\) 开头填 ABC
,BCA
或 CAB
均可。对于在中间的一段,因为我们需要保证每段都是极长的,所以这个段的开头三个字符只有两种填法。若开头的长度 \(\ge 3\),方案数为 \(3\times 2^{k-1}\times \dbinom{a+b+c-2k}{\begin{matrix} a-k & b-k & c-k & k\end{matrix}}\);对于另一种情况,计算是类似的。
时间复杂度 \(O(a+b+c)\)。
ABC 266
Rank 85,Performance 2400。
Ex - Snuke Panic (2D)
设 \(f_i\) 表示在 \(T_i\) 时间恰好位于 \((X_i,Y_i)\) 的情况下,在前 \(T_i\) 秒能获得的最大收益。那么有:
其中 \(\operatorname{cond}(i,j)\) 是:
将绝对值拆开,得到:
注意到 \(T_j<T_i\) 的限制是多余的,于是剩下的就是一个三维数点,对其中一维扫描线,并用二维线段树维护剩下两维即可。
ARC 148
Rank 540,Performance 1803。
D - mod M Game
设给定的数集是 \(S\)。考虑当最后只剩下两个数时,Alice 该如何选择。设 Alice 和 Bob 的数分别是 \(a,b\),剩下的两个数分别是 \(x,y\),如果:
那么 Alice 必败。此时我们需要有 \(a-b\equiv b-a \equiv x-y \pmod{m}\)。有两种情况:\(a\equiv b\pmod{m}\),以及若 \(2\mid m\),还有 \(a\equiv b\pmod{\frac{m}{2}}\)。
可以发现,若 \(x,y\in S\) 且 \(x\equiv y\pmod{m}\),则 Bob 一定会在 Alice 选择 \(x\) 后立即选择 \(y\),因此这样的 \(x,y\) 可以从 \(S\) 中删除。
此时,分 \(m\) 的奇偶讨论:
- 若 \(m\) 是奇数,只需检查 \(S\) 中是否有剩下的数即可,若有则 Alice 必胜,否则 Bob 必胜。
- 若 \(m\) 是偶数,将所有 \(x\equiv y\pmod{\frac{m}{2}}\) 的 \(x,y\) 分为一类,若存在一类中的数的个数是奇数,或者总的类数是奇数,则 Alice 必胜。否则 Bob 必胜。
E - ≥ K
将 \(A_{1\dots N}\) 从小到大排序。
我们维护两个指针 \(l,r\),以及当前能插入的位置个数 \(c\),初始时 \(l=1,r=N,c=1\)。做以下步骤直至 \(l\ge r\):
- 令 \(\mathrm{ans}\gets \mathrm{ans}\times c\);
- 若 \(A_l+A_r\ge K\),则令 \(c\gets c+1,r\gets r-1\);
- 否则,令 \(c\gets c-1,l\gets l+1\)。
最后,我们令 \(\operatorname{ans}\gets \operatorname{ans}\times c\),这是为了计算 \(l=r\) 时 \(A_l\) 能插入的位置个数。因为 \(\{A_n\}\) 中可能有重复数字,所以还需要除以若干阶乘。
这个算法的正确性是显然的,但我很好奇这是怎么想到的。
ARC 150
Rank 316,Performance 2127。
D - Removing Gacha
考虑每个点期望被选的次数,将它们加起来就能得到答案。考虑一个点 \(u\),设它到根的路径上有 \(d\) 个点。我们不妨将“只能选坏的点”改成“所有点都能选”,这样显然不会影响 \(u\) 被选的期望次数。
现在我们是在这 \(d\) 个点中均匀随机地选点,因此这 \(d\) 个点是等价的,不妨先考虑它们被选的总次数,再除以 \(d\) 就是 \(u\) 被选的期望次数。考虑假如现在已经选了 \(i\) 个点,那么期望还需要 \(\frac{d}{d-i}\) 次才能选到一个新的点。因此 \(u\) 被选的期望次数就是 \(\sum_{i=1}^d \frac{1}{i}\),对所有 \(u\) 求和就是答案。
ARC 151
Rank 220,Performance 2286。
D - Binary Representations and Queries
对于任意两个操作 \((X,Y)\) 和 \((X',Y')\),假如 \(X\neq X'\),那么将这两个操作交换不会影响结果。
证明:不妨考虑 \((X,Y)=(0,0),(X',Y')=(1,0)\) 的情况。此时,考虑四个连续的数 \(x,x+1,x+2,x+3\) 满足 \(4\mid x\),模拟以下会发现交换不影响答案。而这个很容易扩展到任意的 \((X,Y),(X',Y')\) 上。
于是我们将所有 \(X\) 相同的归为一类,在其中做一个 \(2\times 2\) 的矩阵乘法即可,时间复杂度 \(O(2^N+Q)\)。
AGC 059
Rank 395,Performance 1991。
A - My Last ABC Problem
首先考虑对于单个字符串 \(S\) 如何计算它的 beauty:将 \(S\) 看作一个环,设 \(k\) 为 \(S\) 中有多少个位置满足相邻两个字母不同。考虑用 \(k\) 的变化来描述方案。对于一次操作,\(k\) 至多减少 \(2\),于是我们知道答案的下界是 \(\lceil \frac{k}{2}\rceil\)。考虑对于一个 \(k\ge 4\),如果将这 \(4\) 对相邻位置提取出来,其中一定有一对相同的(因为只有三种不同的对 \(\mathtt{AB,BC,AC}\))。那么如果对这两个相同的做一次操作,就能使得 \(k\) 减少 \(2\)。当 \(k=3\) 时,串一定形如 \(\mathtt{A...B...C...}\),对 \(\mathtt{B}\) 段和 \(\mathtt{C}\) 段分别做一次操作即可。当 \(k=2\) 时,只需要做一次操作。于是答案就是 \(\lceil \frac{k}{2}\rceil\)。
对于多组询问,预处理前缀和即可。
B - Arrange Your Balls
设 \(C_{1\dots N}\) 中不同的数字有 \(k\) 个,那么答案要不然是 \(k\),要不然是 \(k-1\)。答案为 \(k\) 是容易构造的:将 \(C_{1\dots N}\) 排序即可;所以只需要检查答案是否可以达到 \(k-1\)。
考虑一个将数字插入进环的过程。每次插入一个以前没插入过的数时,都会使答案至少增加 \(1\),至多增加 \(2\)。所以只需要找到一种插入方案,使得每种数插入时,答案都只增加 \(1\)。
将所有种类的数按照出现次数从大到小排序,并按这个顺序插入。假如当前我们要插入 \(c\) 个 \(i\),我们找到一个空隙满足它两边的数字相等,并将这 \(c\) 个 \(i\) 全部插入到空隙中。如果不存在这样的空隙那么答案就是 \(k\)。
用链表维护这个过程即可,时间复杂度 \(O(N)\)。
C - Guessing Permutation for as Long as Possible
对于一个询问 \((a,b)\),设 \(t_{a,b}\) 表示它是第几个询问。考虑三个互不相同的位置 \(u,v,w\) 满足 \(\max(t_{u,v},t_{v,w})<t_{u,w}\),那么不能出现询问 \((u,v)\) 得到的是 \(P_u<P_v\),且询问 \((v,w)\) 得到的是 \(P_v<P_w\) 这种情况。
上述条件也是充分的,证明比较显然。
考虑将每个询问 \((a,b)\) 拆成两个点 \((a,b,0),(a,b,1)\),其中 \((a,b,0)\) 代表答案是 \(P_a<P_b\),\((a,b,1)\) 代表 \(P_a>P_b\)。考虑每组满足上述条件的 \(u,v,w\),有:
- \((u,v,0)\iff (v,w,1)\);
- \((u,v,1)\iff (v,w,0)\)。
于是直接拿并查集维护,如果 \((u,v,0)\) 和 \((u,v,1)\) 在同一个连通块中了,答案就是 \(0\);否则,设最终形成了 \(k\) 个连通块,答案就是 \(2^{\frac{k}{2}}\)。
AGC 060
Rank 281,Performance 2175。
A - No Majority
题目给的条件可以转化成,不能有相邻且相同的字符,且连续三个字符中不能有相同的。于是直接 DP 即可,时间复杂度 \(O(n|\Sigma|^3)\)。
B - Unique XOR Path
考虑给定的这个字符串 \(S\),假如其中包含 RD
,那么可以将其变成 DR
,这样得到的路径与 \(S\) 只会有一个位置之差。如果在 \(S\) 中能找到 \(A\) 对不相交的相邻的 D
和 R
,那么就可以形成 \(2^A\) 种值。于是,只要 \(2^A>2^K\),答案就一定是 No
。否则,答案一定是 Yes
。
C - Large Heap
\(U\) 在这个二叉堆的最左链上,且深度为 \(A\);\(V\) 在最右链上,深度为 \(B\)。
考虑从小到大填数的过程,在任意时刻,已经填过数的节点都会形成连通块。于是设 \(f_{i,j}\) 表示最左链恰好填了深度 \(\le i\) 的,最右链恰好填了深度 \(\le j\) 的概率。有转移:
其中 \(p_{i,j}\) 表示:在已知左右链分别填到深度为 \(i,j\) 的点时,左链上深度为 \(i+1\) 的点 \(U'\) 比右链上深度为 \(j+1\) 的点 \(V'\) 先填上数的概率。赛时直接以为这里 \(p_{i,j}=\frac{1}{2}\),但这明显是错的。
其他子树中的点显然不影响,只需要考虑 \(U'\) 和 \(V'\) 的子树即可。设 \(s_1,s_2\) 分别是以 \(U',V'\) 为根的子树大小,\(p_{i,j}\) 就是长为 \(s_1+s_2\) 的有 \(s_1\) 个 \(0\) 和 \(s_2\) 个 \(1\) 的随机 \(01\) 序列中,第一位是 \(0\) 的概率。因此 \(p_{i,j}=\frac{s_1}{s_1+s_2}\)。
最后考虑答案。枚举当最后一次操作恰好是填 \(U\) 时,右链填到了哪里,于是答案就是
ARC 153
Rank 73,Performance 2699。
C - ± Increasing Sequence
单调递增的限制看起来很烦。考虑这样的转化:令 \(\{y_n\}\) 是 \(\{x_n\}\) 的差分数组,
记 \(s_i\) 等于 \(A_{i\dots n}\) 之和,我们需要找到一个整数数列 \(\{y_n\}\) 满足:
- \(\forall i\in [2,n],y_i>0\);
- \(\sum_{i=1}^n y_is_i=0\)。
并且,这样转化后的 \(\{s_n\}\) 有一个性质,就是这些 \(s_i\) 的值会构成包含 \(0\) 的连续一段区间。于是只有 \(s_i=\pm 1\) 的 \(y_i\) 以及 \(y_1\) 是有用的。分类讨论一下即可。
ABC 288
Rank 96,Performance 2400。
G - 3^N Minesweeper
非常好题目。
类似于做 FMT 的方式,我们从高位到低位逐一确定。设 \(f_{i,S}\) 表示最高的 \(i\) 位在 \(S\) 中对应的位必须相等,剩下的位在 \(S\) 中对应的位只需满足题目说的“相邻”时,满足条件的 bomb 个数。转移就是对 \(i\) 这一位进行容斥。
代码:https://atcoder.jp/contests/abc288/submissions/38626637。
Ex - A Nameless Counting Problem
非常好题目。
定义合法序列是满足如下条件的整数序列:
- 其中每个元素均在 \([0,M]\) 中;
- 所有元素的异或和是 \(X\)。
注意到若 \(A_i=A_{i+1}\),则直接删掉 \(A_i,A_{i+1}\) 不会对整个序列的异或和造成影响。于是,假如能算出 \(g_i\) 表示长为 \(i\) 的不含重复元素的合法序列,那么我们再枚举有多少个重复元素,最终的答案就是
于是只需要考虑如何算 \(g\)。由于 \(x\operatorname{xor} x=0\),所以一个长度为 \(l\) 的含有重复数字的合法序列,一定可以被缩成长度 \(<l\) 的不含重复数字的合法序列。利用这个可以进行容斥,假设当前要计算 \(g_l\),我们先计算 \(f_l\) 表示长为 \(l\) 的合法序列个数,开始时令 \(g_l\gets f_l\)。
再减去包含重复元素的合法序列个数,设:
- 序列中有 \(i\) 个出现了奇数次的元素;
- 序列中有 \(j\) 种出现了奇数次的数字;
- 序列中有 \(k\) 种出现了偶数次的数字。
那么这个序列有重复元素,当且仅当 \(j<l\)。我们可以将这个序列缩成长为 \(j\) 的不包含重复数字的序列,因此对于固定的 \((i,j,k)\),满足条件的序列个数是
其中 \(\mathrm{odd}_{i,j}\) 表示将 \(i\) 个可区分的元素划分成 \(j\) 个不可区分的集合,使得每个集合的大小都是奇数的方案数,\(\mathrm{even}_{i,j}\) 同理。
对于所有的 \(i\in [0,l],j\in [0,l-1],k\in [0,l]\),我们都令 \(g_l\) 减掉上面的式子,最终就能计算出所有 \(g_0,g_1,\dots,g_n\)。
上述所有过程中,只有 \(f\) 的计算是 \(O(N^3\log X)\) 的,其余都是可以做到 \(O(N^3)\) 的。
代码:https://atcoder.jp/contests/abc288/submissions/38666417。
ARC 156
Rank 78,Performance 2658。
C - Tree and LCS
每次剥一层叶子,并把这些叶子的 \(P\) 赋值成它们编号的一个错位排列。由于一个点数 \(>1\) 的树总会有至少两个叶子,所以只会在根结点处出现无法错排的情况。
这样,题目中定义的 similarity 就至多是 \(1\),达到了下界。
ARC 157
Rank 270,Performance 2188。
D - YY Garden
考虑枚举横着放 \(x\) 个栅栏,这样也可以确定竖着需要放多少个栅栏。然后从左往右扫描每列,如果加入这一列以后总的 Y
的个数 \(>2(x+1)\),那么无解。如果 Y
的个数 \(=2(x+1)\),那么可以算出来每个横着的栅栏可以放在哪个区间里。同时如果竖着的列是空的,那么竖着的栅栏也可以随意改变位置。
设 Y
的个数是 \(y\),那么需要满足 \(x+1\mid y,x+1\le n,\frac{y}{x+1}\le m\)。同时满足这些条件的 \(x\) 一定不多,对于每个 \(x\) 都算一下即可。
E - XXYX Binary Tree
由于 \(A+B+C=N-1\),所以可以忽略 XX
的限制。
因为不能出现 YY
,如果一个非叶子节点是 Y
,那么它的两个儿子和父亲都需要是 X
,这样贡献两个 YX
和一个 XY
。如果一个叶子节点是 Y
,那么它的父亲需要是 X
,贡献一个 XY
。
所以设有 \(x\) 个非叶子节点是 Y
,\(y\) 个叶子节点是 Y
,那么 \(x+y=B,2x=C\)。并且只需要再满足不出现 YY
,这个条件就是充分的了。
所以可以 DP。设 \(f_{u,i,0/1}\) 表示 \(u\) 的子树内,有 \(i\) 个非叶子节点是 Y
,且点 \(u\) 是/不是 Y
的情况下,子树内最多能有多少个叶子节点是 Y
。
时间复杂度 \(O(N^2)\)。
ARC 158
Rank 80,Performance 2672。
D - Equation
设 \(F(x,y,z)=(x+y+z)(x^n+y^n+z^n)(x^{2n}+y^{2n}+z^{2n}),G(x,y,z)=x^{3n}+y^{3n}+z^{3n}\)。
注意到 \(F,G\) 都是齐次的,所以 \(F(tx,ty,tz)=t^{3n+1}F(x,y,z),G(tx,ty,tz)=t^{3n}G(x,y,z)\)。
于是,
只要 \(F(x,y,z),G(x,y,z)\) 均非零,就可以解出 \(t\) 得到一组解。
根据官方题解中的证明,只需要直接随机 \(x,y,z\) 即可。
ARC 159
Rank 185,Performance 2329。
C - Permutation Addition
首先考虑有解的必要条件。设 \(s=\sum_{i=1}^n a_i\),注意到每次加一个排列会让 \(s\gets s+\frac{n(n+1)}{2}\),而最终需要有 \(n\mid s\),于是若 \(n\) 是奇数,则必要条件是 \(n\mid s\);若 \(n\) 是偶数,则必要条件是 \(\frac{n}{2}\mid s\)。
考虑如果所有 \(a_i\) 都加了同一个数,那么相当于没加。于是我们可以用两次操作实现:选择两个位置 \(i,j\),令 \(a_i\gets a_i+1,a_j\gets a_j-1\)。因为对于除了这两个位置以外的位置,都可以构造 \(p_1(i)+p_2(i)=n+1\)。
于是每次选择 \(<\frac{s}{n}\) 的一个位置和 \(>\frac{s}{n}\) 的一个位置进行操作即可。
E - Difference Sum Query
题面写得很抽象,但其实就是在做一个类似于二分的东西。考虑建出一棵二叉搜索树,当我们二分到一个深度为 \(t\) 且区间为 \([l,r]\) 的点时,设 \(f(l,r,t)\) 表示 \(l,r,t\) 通过题面上那个式子算出的 \(m\) 的值,我们让 \(f(l,f(l,r,t)-1,t+1),f(f(l,r,t)+1,r,t+1)\) 成为 \(f(l,r,t)\) 的左右儿子。
这样,\(x_i\) 的值就是二叉搜索树上点 \(i\) 的深度。并且,由于这棵二叉树的中序遍历是 \(1,2,\dots,N\),所以对于任意两个编号相邻的点 \(i,i+1\),\(i\) 和 \(i+1\) 一定有祖先后代关系。于是 \(|x_i-x_{i+1}|\) 就是二叉搜索树上点 \(i\) 和 \(i+1\) 的距离。
所以 \(\mathrm{ans}=\sum_{i=c}^{d-1} \operatorname{dist}(i,i+1)\)。因为 \(\mathrm{ans}+\operatorname{dist}(c,d)\) 就是 \(c,c+1,\dots,d\) 这些点构成的虚树的边数乘二(这里的虚树算上那些只有一个儿子的点),而这个虚树只由两部分点构成:
- \(c,c+1,\dots,d\);
- \(c\leadsto d\) 的路径上所有编号不在 \([c,d]\) 间的点。
于是我们只需要算出 \(\operatorname{dist}(c,d)\),以及 \(c\leadsto d\) 的路径上编号不在 \([c,d]\) 间的点的个数,即可求出答案。
由于保证了 \(\max(a_i/b_i,b_i/a_i)\le 2\),所以每次二分至少会干掉 \(\frac{1}{3}\) 的区间长度,所以二叉搜索树的深度是 \(O(\log N)\) 的。所以暴力求出需要的信息即可。
F - Good Division
比较套路的题。
首先,某一段可以单独成段,当且仅当其长度为偶数,且其没有绝对众数。
于是设 \(f_i\) 表示前 \(i\) 个位置有多少种合法的分割方式。转移时,用所有转移减去当前段有绝对众数的转移。
考虑绝对众数的那个套路。枚举一个绝对众数 \(x\),把整个序列里是 \(x\) 的位置标记为 \(1\),其余位置标记为 \(-1\),那么某一段的绝对众数是 \(x\) 当且仅当这一段的标记之和 \(>0\)。我们先把所有是 \(x\) 的位置删去。随后,对于某个是 \(x\) 的位置,我们分别找到它前面和后面距离它最近的没被删去的位置,并把这两个位置删去。然后只需要考虑所有被删去的位置构成的连续段即可,段间一定没有贡献。对于每个连续段,只需要用树状数组维护即可。
但这样有一个问题,就是当前 \(f_i\) 的值依赖于它前面所有 \(f_j\) 的值,所以不可能对于每个绝对众数 \(x\) 分别做上述操作。
考虑把所有这些连续段离线下来做扫描线。对于每个位置,我们先处理它上面记录的加入、删除操作,然后枚举现在仍然存在的每个连续段,并在这个连续段对应的树状数组上修改和查询。
由于所有连续段的长度之和是 \(O(N)\) 的,所以总的时间复杂度是 \(O(N\log N)\)。如果精细实现应该能做到 \(O(N)\),因为那个树状数组部分维护的是一个折线。但比较难写。
\(\Delta\) ARC 127
赛时做出 ABC,赛后做出 D。
C - Binary Strings
逐位确定。首先第一位一定是 \(1\)。考虑后面的位,一种情况是当前位是空的;还有 \(2^l-1\) 种情况是当前位是 \(0\),其中 \(l\) 是还没确定的位的个数。
于是只需要实现把 \(X\) 和 \(2^l\) 比大小,以及令 \(X\gets X-2^l\),或者令 \(X\gets X-1\)。这个题的特殊性质保证了暴力做这个减法是对的。时间复杂度 \(O(N)\)。
D - Sum of Min of Xor
考虑最高的那一位 \(x\) 使得 \(A_i\oplus A_j\) 和 \(B_i\oplus B_j\) 在第 \(x\) 位上不相等,那么有 \(x=\operatorname{highbit}(A_i\oplus B_i\oplus A_j\oplus B_j)\)。
把所有下标 \(i\) 按照 \(A_i\oplus B_i\) 的值插入到 Trie 树中,这样只需要在 Trie 上的某个节点 \(u\) 上考虑它左儿子中的所有点作为 \(i,j\) 中的一个,右儿子中的所有点作为 \(i,j\) 中的另一个的贡献。
根据 \(u\) 本身的信息就可以确定 \(x\),只需要分类讨论 \(A_i,B_i,A_j,B_j\) 在第 \(x\) 位上的值,就可以知道 \(A_i\oplus A_j\) 和 \(B_i\oplus B_j\) 的大小关系。知道大小关系以后,直接考虑每一位的贡献即可。
时间复杂度 \(O(V\log^2 V)\)。
E - Priority Queue
首先考虑,如果给定剩下的数的集合 \(S\),如何判定 \(S\) 是否合法。设 \(S=\{s_1<s_2<\dots<s_k\}\),有如下定理:
把所有 \(1\) 位置的权值设为它前面(包括它本身)\(1\) 的个数,然后顺序考虑所有 \(2\),对于每个 \(2\) 把它前面最后一个 \(1\) 删掉。设剩下的数的权值依次是 \(z_1,z_2,\dots,z_k\)。
\(S\) 合法,当且仅当 \(\forall i,s_i\le z_i\)。
证明可以感性理解。根据这个定理直接进行 DP 即可,时间复杂度 \(O(A^2)\)。
\(\Delta\) ARC 149
赛时做出 ABC。
D - Simultaneous Sugoroku
牛逼题。
设 \(f(x)\) 表示 \(x\) 在经过这 \(M\) 次操作后得到的数。容易发现 \(f(x)=-f(-x)\),所以只需要维护 \(x>0\) 的 \(f(x)\) 即可。
维护区间 \([l,r]\),表示当前 \(x\in [l,r]\) 的 \(f(x)\) 是同号的,并且存在某个常数 \(k\) 使得 \(\forall x\in [l,r],f(x)=x+k\),且其他 \(f(x)\) 的值可以通过这 \(r-l+1\) 个值推算出来。
顺序考虑这 \(m\) 次操作,假设当前考虑到了 \(D_i\),不妨设 \(l>0\),那么 \([l,r]\) 会变成 \([l-D_i,r-D_i]\)。分类讨论这个区间在负半轴上的部分更多还是在正半轴上的部分更多,并把较少的那一边中的点对应向较多的那一边中的点连边。此外,变成 \(0\) 的情况也是好处理的。
在最后对连边形成的树进行一遍 DFS 即可。时间复杂度线性。
E - Sliding Window Sort
硬刚了三个半小时做出来了。
首先考虑 \(K>N-M+1\) 的情况。在前 \(N-M+1\) 次操作结束后,操作就开始绕圈了。此时一定是序列中的前 \((M-1)\) 大值聚在序列的最后。在接下来的操作中,一定是这 \(M-1\) 个数绕着序列循环移动,每次把这一整段和它后面的第一个位置交换。
这个交换操作并不会影响什么,于是先考虑 \(K=N-M+1\) 的情况。考虑题目中的操作,相当于:\(B_i\) 是 \(A_{0\dots (M+i-1)}\) 中删去 \(B_0,\dots,B_{i-1}\) 再加入 \(A_{M+i}\) 后的最小值。
可以发现:对于 \(B\) 中一个是前缀最大值的位置 \(i\),\(B_i\) 可以填在 \(A_{0\dots (M+i-1)}\) 中任意一个没被填过的位置,于是它可以使答案乘上 \(M\);否则,一定有 \(A_i=B_i\)。
现在还有最大的 \(M-1\) 个数没有确定填的位置。由于只剩下了 \(M-1\) 个位置可填,所以将答案再乘上 \((M-1)!\) 即可。
再讨论一下 \(K>N-M+1\) 的情况。我们只需要求出来在执行这 \(K-(N-M+1)\) 次操作前,序列的开头是什么,然后变成 \(K=N-M+1\) 的情况即可。可以发现,序列的开头一开始在 \(0\),进行一次操作后变成了 \(N-2\),此后每 \(N-M+1\) 次操作会使得开头的位置循环左移 \(M-1\)。这样就求出了开头位置。
\(K<N-M+1\) 的情况也是好处理的,只需要把序列末尾从来没变过的元素删去,然后把剩下的元素离散化一下,就也变成了 \(K=N-M+1\) 的情况。
时间复杂度 \(O(N)\)。
F - Rational Number System
首先考虑,如果给定正整数 \(x\),怎么把它转化成 \(\frac{p}{q}\) 进制数。这显然就是,每次提取 \(x\bmod p\) 作为当前位,然后令 \(x\gets \lfloor\frac{x}{p}\rfloor\times q\)。这同时也说明了 \(\frac{p}{q}\) 进制数的长度不会超过 \(\log_{\frac{p}{q}} N\le 4200\)。
非整数进制的一个很大的麻烦是,它的一个表示 \((a_1,a_2,\dots,a_k)\) 不一定对应一个整数。但有一个很强的性质:对于一个正整数 \(x=(a_1,a_2,\dots,a_k)\),所有的 \((a_1,a_2,\dots,a_i)\),其中 \(1\le i\le k\),对应的都是整数。
也就是说,可以用这样的方法生成所有正整数:从数字 \(0\) 开始,每次取出一个已经被生成出来的数 \(x\),若 \(q\mid x\),则 \(\frac{px}{q},\frac{px}{q}+1,\dots,\frac{px}{q}+p-1\) 这些数都可以通过在 \(x\) 的 \(\frac{p}{q}\) 进制表示的末尾添加上一个数来生成。
这个生成的过程形成了一个 Trie 的结构,并且这棵 Trie 的 BFS 序一定是 \(1,2,\dots,N\)。考虑现在要求出 Trie 上字典序第 \(L\) 大的路径对应的数字,从前往后逐位确定,每次进行一个二分,假设当前需要 check 的是 \(m\),我们需要支持的就是查询 Trie 上当前节点的编号 \(\ge m\) 的所有儿子的子树大小之和。由于 BFS 序是按顺序排列的,所以这些子树内深度相同的点形成了一段区间。只需要算出这段区间的左右端点即可,而这是好算的。单次 check 的时间复杂度是 \(O(\log_{\frac{p}{q}} N)\),而至多需要查询 \(\log_{\frac{p}{q}} N\times \log p\) 次,于是这一部分的时间复杂度是 \(O(\log^2_{\frac{p}{q}} N\times \log p)\)。
现在我们知道了字典序第 \(L\) 小的节点是哪个,需要求出第 \((L+1)\dots R\) 小的节点。模拟 DFS 并回溯的过程即可做到 \(O(R-L)\)。
总结:
- 要尽量往经典的结构上想。比如这题的 Trie,再比如 ARC159E 的二叉搜索树。
- 想不出来性质的时候可以画一下这些结构。
\(\Delta\) ARC 146
赛时做出 AB,赛后做出 D。
C - Even XOR
设 \(\operatorname{xor}(S)\) 表示 \(S\) 中元素的异或和。
假如现在有一个合法集合 \(S\),考虑还能往里面放哪些元素。对于一个数 \(x\),假如存在一个 \(T\subseteq S\) 使得 \(2\nmid |T|\) 且 \(\operatorname{xor}(T)=x\),那么 \(x\) 不能放,否则能放。
考虑一个性质:对于任意两个 \(T_1,T_2\subseteq S\) 且 \(2\nmid |T_1|,2\nmid |T_2|\),一定有 \(\operatorname{xor}(T_1)\neq\operatorname{xor}(T_2)\)。证明是比较显然的。
于是,对于一个大小为 \(i\) 的集合,恰好有 \(2^{i-1}\) 个数不能放进去。注意到集合大小一定 \(\le n+1\),于是设 \(f_i\) 表示大小为 \(i\) 的合法集合个数,转移是
其中 \(\frac{1}{i+1}\) 是因为大小为 \(i+1\) 的集合会被其中每个元素都贡献一次。
D - >=<
因为限制是双向的,所以先把每个限制都拆成两个。
如果不存在 \(X_i=1\) 和 \(Y_i=1\),那么所有数都取 \(1\) 即可。
于是考虑一个形如 \(i\ 1\ j\ y\) 的限制。它其实相当于限制了 \(A_j\) 需要 \(\ge y\)。而 \(A_j\ge y\) 又会限制:
- 对于那些满足 \(P_x=j\land X_x<y\) 的限制 \(x\),我们需要限制 \(A_{Q_x}>Y_x\);
- 对于那些满足 \(P_x=j\land X_x=y\) 的限制 \(x\),我们需要限制 \(A_{Q_x}\ge Y_x\);
继续递归考虑这些限制,直到所有限制都处理完。此时,如果某个 \(A_i\) 必须 \(>m\),那么无解;否则,每个元素都一定可以取它能取的最小值。
因为每条限制都只会被考虑 \(O(1)\) 次,所以总的时间复杂度是 \(O((N+M)\log N)\),瓶颈在于排序。
E - Simple Speed
为啥我没想出来!!!
如果想到了转化成折线,那么就输了。
考虑直接做。从小到大考虑每个 \(i\),把 \(A_i\) 个 \(i\) 插入到当前数组里。设 \(f_{i,j,0/1,0/1}\) 表示考虑 \(A_{1\dots i}\),且当前有 \(j\) 对相邻的 \((i,i)\),且左右端点处不是/是 \(i\) 的方案数。
不妨仅讨论一下那种左右端点处不插入新数字的情况。此时,设 \(c=A_{i+1}-j\),那么转移就是
其他情况的转移是类似的。
并且,注意到 \(j\) 那一维只有 \(O(1)\) 种取值,于是做完了。时间复杂度 \(O(N)\)。
\(\Delta\) ARC 145
赛时做出 ABC,赛后做出 D。
D - Non Arithmetic Progression Set
我的做法
先不考虑那个和为 \(M\) 的限制,只需要构造出来一个大小为 \(N-1\) 的不含等差数列的集合。考虑随机化,每次随机一个 \([-10^7,10^7]\) 间的数尝试插入集合,时间复杂度 \(O(N^2)\)。
最后,设 \(x=M-\sum_{i\in S} i\),我们需要检查 \(x\) 是否能插入到集合里。如果不能插入的话整个就寄了,需要重新随机,显然不行。
但可以打表。预先随机出来一个大小为 \(17000\) 的合法集合 \(S\)。每次,我们在这个集合里选择 \(N\) 个数作为当前集合。维护当前选择的集合内所有数的和 \(s\),如果 \(s<M\) 那么在 \(S\cap [0,\infty)\) 中随机,否则在 \(S\cap (-\infty,0]\) 中随机。这样能保证最后需要插入的 \(x\) 一定在 \([-10^7,10^7]\) 范围内,而且我们可以 \(O(N)\) 地检查 \(x\) 能否插入。这样做一轮是 \(O(N)\) 的,有足够的时间随机很多轮。
代码长度 144KB,感谢 AtCoder 宽松的代码长度限制。
官方做法
\(S\) 不含等差数列,当且仅当对于任意互不相同的数 \(a,b,c\in S\),均有 \(2b\neq a+c\)。
考虑构造 \(S\) 为所有三进制下只有 \(0\) 和 \(1\) 的数。这样,由于 \(a\neq c\),\(a+c\) 中一定有一位是 \(1\)。而 \(2b\) 中一定只有 \(0,2\),于是这个构造是对的。
最后我们需要让 \(S\) 满足“和为 \(M\)”这个限制。由于把 \(S\) 中所有数都加上某个数,不会影响 \(S\) 的合法性,所以只需要让 \(\operatorname{sum}(S)\equiv M\pmod N\) 即可。这可以通过先把 \(S\) 中所有数的最低位空出来,最后根据 \(\operatorname{sum}(S)\bmod N\) 的值来确定这些位来实现。
ARC 160
Rank 188,Performance 2285。
D - Mahjong
考虑如何判断一个序列 \(A\) 是否合法。只考虑第二种操作,我们的目标是让每个 \(A_i\) 都能被 \(K\) 整除。从左往右考虑每个 \(A_i\),对 \(A_i,A_{i+1},\dots,A_{i+K-1}\) 做 \(A_i \bmod K\) 次二操作。最后,只要 \(A_{i-K+2},A_{i-K+3},\dots,A_N\) 都能被 \(K\) 整除,且所有 \(A_i\) 均非负,那么这个 \(A\) 就合法。
设 \(B_i\) 表示在第 \(i\) 个位置做了 \(B_i\) 次二操作,则所有合法的 \(A\) 与所有满足 \(0\le B_i<K\) 的 \(B\) 一一对应。
于是就可以计数了。对 \(B_i<K\) 这个限制进行容斥,然后再用范德蒙德卷积化简即可。
E - Make Biconnected
首先,所有叶子节点一定需要选至少一次,因为如果有某个叶子没被选,那么与它相连的那个点就一定是割点。设叶子个数为 \(k\),对 \(k\) 的奇偶性分类讨论:
- 有偶数个叶子:一定能找到一个非叶子节点 \(u\),使得以 \(u\) 为根时,\(u\) 的所有儿子的子树中叶子节点的个数都不超过 \(\frac{k}{2}\)。这样就一定能给每个叶子节点 \(x\) 找到一个与它配对的叶子 \(y\),使得 \(\operatorname{LCA}(x,y)=u\)。
- 有奇数个叶子:枚举一个叶子 \(x\),对于剩下的 \(k-1\) 个叶子用上述方法配对。考虑找到 \(x\) 往上的第一个三度点 \(v\),那么 \(x\) 能和除了 \(x\leadsto v\) 路径上的点以外的所有点配对。选取其中点权最小的即可。
F - Count Sorted Arrays
题目给的这种形式相当于一个简单的排序网络。根据排序网络的结论,如果我们需要判定排列 \(\{p_N\}\) 是否能被排序,我们只需要判定这样的 \(N\) 个 \(01\) 序列能否被排序:
- 第 \(i\) 个 \(01\) 序列是:将 \(p\) 中所有值 \(\le i\) 的位置标记为 \(0\),其余位置标记为 \(1\)。
从另一方面,对于两个长为 \(N\) 的 \(01\) 序列 \(a,b\),假如 \(a,b\) 只有一位不同,且 \(a<b\),那么我们在 \(a,b\) 间连一条有向边。这样,所有从 \(0\) 到 \(2^N-1\) 的路径,与长度为 \(N\) 的排列一一对应。
那么,对于一次操作 \((a,b)\),我们需要求出来有哪些 \(01\) 序列 \(x\),它当前仍然有 \(x_a=1\) 且 \(x_b=0\)。由于只会有 \(O(N^2)\) 个有效操作,所以可以开 \(N^2\) 个桶来记录,在每次有效操作后重构所有桶。
假如一个 \(01\) 序列在这次操作后被排序了,那么我们就算一下从 \(0\) 到 \(2^N-1\) 的经过这个点的路径条数,将路径条数加到答案里即可。
时间复杂度 \(O(N^42^N+N3^N+M)\)。
\(\Delta\) ARC 161
赛时做出 ABD。
C - Dyed by Majority (Odd Tree)
从剥叶子的角度考虑会有很多细节,所以不妨直接考虑 DFS。一棵子树的根节点有可能会要求其父亲是某种颜色的。在 DFS 过程中检查这样的染色是否合法即可。
E - Not Dyed by Majority (Cubic Graph)
由于题目要求的是不能被生成出来的颜色序列,所以猜测这样的颜色序列个数一定很多,可以直接随机然后用 2-SAT 判断。
F - Everywhere is Sparser than Whole (Judge)
先考虑有没有一个子图的 density 大于 \(D\)。假如一个点集 \(S\) 的导出子图的 density 大于 \(D\),说明
那么考虑 \(T=[N]\setminus S\) 这个点集,有
其中 \(\mathrm{adj}_u\) 是 \(u\) 的所有邻边。
这个式子的形式与 Hall 定理完全相同。于是,考虑这样一个二分图多重匹配建模:左部 \(N\) 个点,所有点可匹配的次数均为 \(D\);右部 \(ND\) 个点,每个点可匹配的次数为 \(1\)。对于原图中的第 \(i\) 条边 \((u,v)\),从左部点 \(u,v\) 向右部点 \(i\) 连边。
再考虑有没有一个 \([N]\) 的真子集 \(S\) 的 density 等于 \(D\)。仍然考虑刚才的建模,现在每个点都匹配了恰好 \(D\) 条它的邻边,我们要找到一个左部点的真子集 \(S\) 使得 \(S\) 只能匹配它当前匹配的边集。
根据二分图匹配的可行边与必经边那套理论,这样的 \(S\) 就对应了构造出的有向图里的一个 SCC。于是把有向图建出来以后检查一下整张图是否强连通即可。
ARC 162
Rank 46,Performance 2848。
F - Montage
通过打表,可以发现合法的 \(A\) 数组形如:
- 若干行、若干列全是 \(0\);
- 去掉全 \(0\) 的行列后,\(0\) 的位置是 \((1,[1,l_1]),(2,[1,l_2]),\dots,(N,[1,l_N])\) 和 \((1,[r_1,M]),(2,[r_2,M]),\dots,(N,[r_N,M])\),其中 \(M>l_1\ge l_2\ge \dots\ge l_N=0\),且 \(r_1=M+1\ge r_2\ge \dots\ge r_N\ge 1\)。并且,对于每个 \(i\) 都有 \(l_i+1<r_i\)。
我们先不考虑全 \(0\) 的行列,对剩下的行列进行 DP。设 \(f_{i,j,k}\) 表示考虑前 \(i\) 行,且 \(l_i=j,r_i=k\) 的方案数,转移形如一个矩形加,可以用二维前缀和将转移优化至 \(O(1)\)。
设 \(F(N,M)\) 是上述 DP 的结果,那么最终的答案就是
直接做是 \(O(N^2M^3)\) 的。但注意到所有的转移都可以放在一起做(开始时将 \(f_{0,j,k}\) 设置为 \(\binom{M}{k-1}\)),这样就 \(O(NM^2)\) 了。
\(\Delta\) ARC 155
赛时做出 BC。
A - ST and TS Palindrome
\(K<2N\) 的情况我们是会做的。
当 \(K\ge 2N\) 时,题目要求的是 \(SS'=S'^RS^R\) 和 \(S'S=S^RS'^R\)。那么 \(S'\) 的前 \(N\) 位和后 \(N\) 位就一定是 \(S^R\)。设 \(S'=S^RTS^R\),要求 \(SS^RTS^R=ST^RSS^R\) 和 \(S^RTS^RS=S^RST^RS\)。
可以约掉一部分,变成 \(S^RT=T^RS\) 和 \(TS^R=ST^R\)。这样就递归到了 \(|T|=|S'|=2N\) 的子问题。所以 \(K\) 可以对 \(2N\) 取模,转化为 \(K<2N\) 的情况。
D - Avoid Coprime Game
对于一个固定的 \(G\),那些满足 \(\gcd(a_i,G)<G\) 的 \(a_i\) 一定没有被选过;其他的 \(a_i\) 一定有 \(G\mid a_i\),选择其中任意一个的效果都是一样的,所以只需要记录选择这样的数的次数的奇偶性。
设 \(f_{i,j}\) 表示当 \(G=i\) 且操作次数的奇偶性是 \(j\) 时,先手胜还是后手胜。假如这一次操作让 \(G\) 变小了,那么枚举变小后的值 \(x\),需要存在一个 \(a_i\) 使得 \(\gcd(a_i,G)=x\)。如果 \(f_{x,1-j}\) 是 \(0\) 的话,\(f_{i,j}\) 就是 \(1\)。
如果不存在一个 \(f_{x,1-j}\) 是 \(0\),那么当前的先手就会选择一个 \(G\) 的倍数来拖时间。轮到后手时,如果后手有必胜方案,那么后手胜;否则后手也会拖时间,由于已经知道了可以用来拖时间的数的个数,所以可以算出这样的情况下最后是谁胜利。
处理 \(\gcd(a_i,G)=x\) 的限制可以用莫比乌斯反演,时间复杂度 \(O(\sum_{i=1}^N (\tau_0(i))^2)=O(N\log^3 N)\),有一个 \(\frac{1}{\pi^2}\) 的常数。
E - Split and Square
当集合 \(S\) 中有 \(0\) 时,每次操作可以恰好消掉 \(S\) 的一个基。
当 \(S\) 不含 \(0\) 时,将 \(S\) 中每一个元素都异或上 \(A_1\),这样在一次操作后的集合不会改变,且 \(S\) 中一定含有 \(0\)。需要特判 \(N=1\)。
求出 \(S\) 的线性基个数即可。