AGC VP 记录 2
AGC VP 记录
为了防止上一个内容太多比较卡,故新开了一个。
AGC041~AGC060
AGC060
[AGC060A] No Majority
skip。Submission #69562933 - AtCoder Grand Contest 060
[AGC060B] Unique XOR Path
给定一个 \(n\times m\) 的网格和 \(k\),和一条从 \((1,1)\) 到 \((n,m)\) 的由向下和向右构成的路径,判断能否给每个格子填一个 \([0,2^k-1]\) 的数,满足在所有从 \((1,1)\) 到 \((n,m)\) 的由向下和向右的路径中,给定的路径是唯一一条异或为 \(0\) 的路径。
\(T\le 100,n,m,k\le 30\)
一个初步的想法是,给 \((1,1)\) 填上 \(2^k-1\),然后给每个拐点处填上某个 \(2^p\),于是条件就是拐点数 \(\le k\)。但是这不是必要的,我们考虑,一条路径在每个拐点处都可以换一种拐弯方式,形成一个只和原路径只差一格的路径。设有 \(x\) 个拐点,如果拐点间是独立的,那么相当于是 \(x\) 个数的线性基能否凑出 \(0\),需要有 \(x\le k\)。
但是如果有连续两个拐弯,那么这两个拐弯不是独立的,可以发现连续 \(x\) 个拐弯只需要 \(\lceil\frac x 2\rceil\) 个数即可,所以我们统计出 \(\sum \lceil\frac x 2\rceil\) 即可。最后构造的话,我们将这条路径上的数放 \(0\),拐点处放某个 \(2^p\),然后一直向左下或右上延伸到边缘。
Submission #69563120 - AtCoder Grand Contest 060
[AGC060C] Large Heap
称一个 \(1\sim 2^n-1\) 的排列 \(p\) 是好的,当且仅当 \(\forall 1\le i< 2^{n-1}\),有 \(p_i < p_{2i}\) 且 \(p_i < p_{2i+1}\)。给定 \(a,b\),令 \(u = 2^a,v = 2^{b+1}-1\),求在所有好的排列中任意选一个,\(p_u < p_v\) 的概率是多少。对 \(998244353\) 取模。
\(n\le 5000\)
将 \(p\) 看成一个深度为 \(0\sim n-1\) 的满二叉树,那么条件就相当于一个节点的权值要小于两个儿子的权值,\(u\) 是根节点一直往左走的深度为 \(a\) 的点,\(v\) 是根节点一直往右走的深度为 \(b\) 的点。于是dd可以将排列看成拓扑序,即在所有拓扑序中任选一个,求 \(u\) 比 \(v\) 先枚举到的概率。
可以发现我们只用关心拓扑时,根节点一直往左走能走到哪,和一直往右走能走到哪,因为拓扑一个其他点对 \(u,v\) 的先后顺序是没有影响的。设 \(f_{x,y}\) 表示根节点往左能走到深度为 \(x\) 的点,往右能走到深度为 \(y\) 的点的状态的概率,然后看下一步会先走哪个子树内的点。
因为是拓扑序,所以下一步会走哪个子树的概率是与子树大小成正比的,两个点的子树大小分别为 \(2^{n-x-1},2^{n-y-1}\),设为 \(p,q\),于是转移为 \(f_{i+1,j}\larr f_{i,j}\frac{p-1}{p-1+q-1},f_{i,j+1}\larr f_{i,j}\frac{q-1}{p-1+q-1}\)。最后答案为 \(\sum\limits_{i=0}^{b-1} f_{a,i}\),复杂度 \(\mathcal{O}(n^2\log n)\)。
Submission #69563199 - AtCoder Grand Contest 060
[AGC060D] Same Descent Set
求有多少个 \(1\sim n\) 的排列对 \((p,q)\) 满足:
- \(\forall 1\le i < n\),\(p_i > p_{i+1}\and q_i > q_{i+1}\) 或 \(p_i < p_{i+1}\and q_i < q_{i+1}\) 中有一个成立。
答案对 \(998244353\) 取模。\(n\le 2\times 10^5\)
我们发现要求 \(p_i < p_{i+1},q_i < q_{i+1}\) 中两个都成立或都不成立,这比较像异或操作,于是我们设 \(a_i = \begin{cases}1& p_i < p_{i+1}\\-1 &otherwise\end{cases}\),\(b_i\) 同理,于是我们要求 \(a_ib_i = 1\)。但是这仍然不好计算,我们希望一对排列的贡献是 \(\prod\limits_{i=1}^{n-1}a_ib_i\),但事实上如果 \(a_ib_i=-1\) 那么贡献为 \(0\),于是我们可以用钦定的方法。即只钦定一些位置,计算这些位置的 \(a_ib_i\) 之积,那么原来 \(a_ib_i=-1\) 时的贡献就是 \(0\),\(a_ib_i=1\) 时就是 \(2\),最后将答案除以 \(2^{n-1}\) 即可。
考虑所有钦定了的位置的极长连续段,假设我们求出了 \(g_m\) 表示所有长为 \(m\) 的排列的 \(\prod\limits_{i=1}^{m-1}a_ib_i\) 之和,那么贡献就是所有连续段长度的 \(g_m\) 之积。因为排列间要钦定相对大小,所以设 \(G = \sum\limits_i \frac{g_i}{i!i!}x^i\),那么答案就是 \(n!n![x^n]\frac{1}{1-G}\)。
接下来考虑求 \(g\),因为 \(g_m\) 是 \(\prod\limits_{i=1}^{m-1}a_ib_i\) 之和,所以两个排列是独立的,我们只需要求出 \(g'_m\) 表示所有长为 \(m\) 的排列的 \(\prod\limits_{i=1}^{m-1} a_i\) 之和,就有 \(g_m = {g'_m}^2\)。
我们依然用钦定一些位置的做法来考虑,于是贡献就变成了 \(a_i-1\),即 \(p_i < p_{i+1}\) 时贡献为 \(0\),否则为 \(-2\)。那么设 \(h_m\) 表示所有长度为 \(m\) 的排列的 \(\prod\limits_{i=1}^{m-1}(a_i-1)\) 之和,可以发现只有当这个排列为 \(m\sim 1\) 时贡献不为 \(0\),即 \(h_m = (-2)^{m-1}\)。然后依然是设 \(H = \sum\limits_i \frac{h_i}{i!}x^i\),那么 \(g'_i = i![x^i]\frac{1}{1-H}\)。用多项式求逆即可做到 \(\mathcal{O}(n\log n)\)。
Submission #69565000 - AtCoder Grand Contest 060
[AGC060E] Number of Cycles
设 \(f(a)\) 表示排列 \(a\) 中的置换环数量,给定一个 \(1\sim n\) 的排列 \(p\) 和正整数 \(k\),构造一个 \(1\sim n\) 的排列 \(x\) 满足 \(f(x)+f(x\circ p) = k\)。或者报告无解。
\(x\circ p\) 表示 \(x\) 复合上 \(p\) 的排列,即排列 \(y\) 满足 \(y_i = p_{x_i}\)。
\(n\le 2\times 10^5\)
给出一个比较简洁的 \(\mathcal{O}(n)\) 做法。
我们考虑用调整法,设 \(y = x\circ p\),初始时设 \(x_i = i,y_i = a_i\),每次选择 \(i,j\) 并同时交换 \((x_i,x_j),(y_i,y_j)\)。可以发现如果交换 \((x_i,x_j)\),当 \(x_i,x_j\) 处于同一个环中时会分裂为两个环,否则会合并为一个环,即 \(f(x)\) 的变化量为 \(-1,1\),\(y\) 同理。那么 \(f(x)+f(y)\) 的变化量为 \(-2,0,2\),即奇偶性不会改变。
考虑求出 \(f(x)+f(y)\) 最大能取到多少。我们任意取一个满足 \(f(x)+f(y)\) 最大的 \(x\),如果 \(x\) 有某一个环长度 \(>1\),那么将这个环拆为两个环 \(f(x)+f(y)\) 一定不会减小,而因为 \(f(x)+f(y)\) 已经是最大的了所以不会改变。于是我们一直操作下去直到所有环长度为 \(1\),即 \(x_i=i\),此时 \(f(x)+f(y) = n+f(p)\),也就是 \(f(x)+f(y)\) 能取到的最大值,设为 \(s\)。
那么如果 \(k>s\) 或 \(k\) 和 \(s\) 不同奇偶那么一定无解,否则一定有解,下面给出一种构造。还是考虑调整法,初始时 \(x_i=i,y_i=a_i\),并实时维护 \(s\),初始 \(s = n+f(p)\)。
依次枚举 \(y\) 的每个置换环,将每个环上的数依次写下来,设为序列 \(b\)。我们依次枚举 \(i\) 从 \(2\) 到 \(n\),每次要将 \(x_{b_1}\sim x_{b_i}\) 连成一个环,同时要将 \(y_{b_1},\ldots,y_{b_i}\) 连成一个或两个环,其余位置不管。假设已经考虑完了 \(1\sim i-1\),设 \(lst\) 表示 \(y\) 中 \(b_1,\ldots,b_{y-1}\) 里面的某个和 \(b_1\) 不在同一个环中的点,如果没有就是 \(0\),分以下几种情况考虑:
- 如果 \(y_{b_i},y_{b_{i-1}}\) 不属于一个环,那么交换 \((x_{b_1},x_{b_i}),(y_{b_1},y_{b_i})\),\(lst\) 不变,并将 \(s\) 减 \(2\)。
- 如果 \(y_{b_i},y_{b_{i-1}}\) 属于一个环,并且 \(lst\ne 0\),那么就交换 \((x_{lst},x_{b_i}),(y_{lst},y_{b_i})\),将 \(lst\) 赋为 \(0\),\(s\) 减 \(2\)。
- 如果 \(y_{b_i},y_{b_{i-1}}\) 属于一个环,并且 \(lst=0\),那么就交换 \((x_{b_1},x_{b_i}),(y_{b_1},y_{b_i})\),将 \(lst\) 赋为 \(b_i\),\(s\) 不变。
可以发现,当 \(i\) 枚到 \(n\) 的时候 \(s\) 一定为 \(2\) 或 \(3\),取决于 \(n+f(p)\) 的奇偶性,此时一定有 \(k\ge s\),那么中途一定存在一个时刻满足 \(s=k\),在这个时刻退出循环并输出答案即可。复杂度 \(\mathcal{O}(n)\)。
Submission #70354132 - AtCoder Grand Contest 060
[AGC060F] Spanning Trees of Interval Graph
有一张无向图,图中每个点都是一个区间,\(\forall 1\le l\le r\le n\),满足区间 \([l,r]\) 有 \(c_{l,r}\) 个。两个点之间有连边当且仅当它们对应的区间有交,求这张图有多少棵生成树。
答案对 \(998244353\) 取模。\(n\le 400,1\le C_{i,j}\le 10^4\)
神仙题。
首先你需要会 Matrix-Tree 定理,接下来有个引理 Matrix determinant lemma:
设 \(A\) 是一个可逆矩阵,\(u,v\) 是两个列向量,则:
\[det(A+uv^T) = det(A)(1+v^TA^{-1}u) \]证明:
先考虑 \(A=I\) 的情况,有如下式子:
\[\begin{pmatrix} I & 0 \\ v^T & 1 \end{pmatrix} \begin{pmatrix} I+uv^T & u \\ 0 & 1 \end{pmatrix} \begin{pmatrix} I & 0 \\ -v^T & 1 \end{pmatrix} = \begin{pmatrix} I & u \\ 0 & 1+v^Tu \end{pmatrix} \]两边同时取 \(det\),则所有矩阵只需要考虑对角线上的乘积,左边第一个和第三个矩阵取 \(det\) 后都是单位矩阵,于是有:
\[det(I+uv^T) = 1+v^Tu \]现在考虑一般情况,我们可以将 \(u\) 设为 \(A^{-1}u\),即:
\[det(A+uv^T) = det(A+A(A^{-1}u)v^T) = det(A)det(I+(A^{-1}u)v^T) = det(A)(1+v^TA^{-1}u) \]这个结论还能继续拓展。设 \(A\) 是一个 \(n\times n\) 的可逆矩阵,\(u,v\) 是 \(n\times m\) 的矩阵,则有:
\[det(A+uv^T) = det(A)det(I_m+v^TA^{-1}u) \]
设 \(S = \sum c_{i,j}\),那么原图有 \(S\) 个点,设 \([l_i,r_i]\) 表示第 \(i\) 个点代表的区间。设 \(D\) 和 \(G\) 表示原图的度数矩阵和邻接矩阵去掉第一行第一列的结果,我们要求 \(det(D-G)\)。其中 \(D_{i,i} = \sum\limits_{j=1}^S [[l_i,r_i]\cap[l_j,r_j]\ne \empty]\),\(G_{i,j} = [[l_i,r_i]\cap[l_j,r_j]\ne \empty]\),注意 \(D_{i,i}\) 将 \(i\) 自己多算了一次,但由于 \(G_{i,i} = 1\) 也多算了一次,所以 \(D-G\) 不影响。
考虑使用上述定理,如果我们能找到两个 \(S\times m\) 的矩阵 \(u,v\) 满足 \(uv^T = G\),那么就有:
而因为 \(D\) 只在对角线上有值,所以 \(det(D)\) 和 \(D^{-1}\) 都是好算的,可以对每个区间 \([l,r]\) 算出与多少个点有交。现在问题是如何找到一个较小的 \(m\) 让 \(uv^T = G\),如果能找到我们就可以在 \(\mathcal{O}(m^3)\) 的复杂度内计算 \(det(I_m-v^TD^{-1}u)\)。
两个区间 \([l_1,r_1],[l_2,r_2]\) 之间连边的条件是它们有交,可以考虑点边容斥,即用两个区间交的点数减去两个区间交的边数来刻画两个区间是否有交。于是我们令 \(m=2n-1\),编号为 \(2i-1\) 的点表示表示点 \(i\),编号为 \(2i\) 的点表示边 \([i,i+1]\)。则:
- \(u_{i,2j-1} = v_{i,2j-1} = [j\in[l_i,r_i]]\)
- \(u_{i,2j} = [[j,j+1]\in[l_i,r_i]]\)
- \(v_{i,2j} = -[[j,j+1]\in[l_i,r_i]]\)
于是我们算出 \(I_m-v^TD^{-1}u\) 的每一项然后高消即可。具体地,\(v^TD^{-1}u\) 第 \(i\) 行第 \(j\) 列元素的值为 \(\sum\limits_{k=2}^S v_{k,i}D_{k,k}u_{k,j}\),相当于求出同时包含 \(i,j\) 代表的点/边的所有 \(D_{k,k}\) 之和,预处理出 \([i,j]\) 与多少个点有交的二维前缀和即可。总复杂度为 \(\mathcal{O}(n^3)\)。
Submission #70676858 - AtCoder Grand Contest 060
AGC059
[AGC059A] My Last ABC Problem
定义一个由 ABC 构成的字符串 \(s\) 的美丽度为,最少用多少次如下操作可以使得 \(s\) 中所有字符相同:
- 选择一个 \(s\) 的子串 \(s_{l,\ldots,r}\) 和一个 ABC 到 ABC 的双射,将 \(s_{l,\ldots,r}\) 中的每个字符做一次映射。
给定一个长度为 \(n\) 的字符串 \(s\) 和 \(q\) 次询问,每次给出 \([l,r]\),求 \(s_{l,\ldots,r}\) 的美丽度。
\(n,q\le 10^5\)
可以发现字符相同的段可以缩起来,则每次操作至多删除两个字符。手玩发现,对于长度 \(\ge 5\) 的串,每次一定可以删除两个字符,而对于所有长度为 \(4\) 的串,答案一定为 \(2\),所以如果 \(|s|\) 为偶数,那么答案就是 \(\frac{|s|}{2}\)。
否则,最后一步删到长度为 \(3\) 时,答案取决于最左和最右边的两个字符是否相同,而这两个字符就是一开始的 \(s\) 最左和最右的字符,答案为 \(\lceil\frac{|s|-1+[s_1\ne s_{|s|}]}{2}\rceil\)。处理出 \([s_i\ne s_{i-1}]\) 的前缀和数组即可 \(\mathcal{O}(1)\) 回答询问,复杂度为 \(\mathcal{O}(n+q)\)。
Submission #69582718 - AtCoder Grand Contest 059
[AGC059B] Arrange Your Balls
skip。Submission #69583068 - AtCoder Grand Contest 059
[AGC059C] Guessing Permutation for as Long as Possible
有一个 \(1\sim n\) 的排列 \(p\),现在你需要确定这个排列。给定 \({n\choose 2}\) 组 \((a_i,b_i)\),满足它们是所有 \(1\le i < j\le n\) 的所有 \((i,j)\) 的某个排列。你会依次枚举 \(i\) 从 \(1\sim {n\choose 2}\),并询问 \(p_{a_i},p_{b_i}\) 间的大小关系,但如果此次询问能直接从之前的询问中推出答案,则你会跳过此次询问。
求有多少个 \(p\) 满足,你不会跳过任何一次询问。答案对 \(10^9+7\) 取模。\(n\le 400\)
初始时有 \(n\) 个点,枚举每次询问,每次相当于看 \(a_i,b_i\) 是否其中一个能到达另一个,能到达就不合法,否则就会询问,然后连一条有向边。将有向边看成无向边,那么如果 \((a_i,b_i)\) 之间不连通肯定合法,否则就相当于所有包含 \((a_i,b_i)\) 的环中,路径的方向不能一样。
可以发现,如果这条环的点数 $ > 3$,因为所有边最终都会被连接,那么我们一定存在一个环内的距离为 \(2\) 的弦,并且这条边的条件严格强于当前边。所以,我们只用考虑所有大小为 \(3\) 的环。于是枚举所有三元环,就可以得到一些限制,每个限制要求两条边的指向要么相同要么相反,于是可以用扩域并查集来维护。
最终统计答案如果某条边不合法那么答案就是 \(0\),否则,答案就是 \(2\) 的连通块次方,因为这些连通块之间一定互不影响(这是因为每次询问都合法),并且知道了所有边的方向,所以一定可以唯一对应到某个排列。复杂度为 \(\mathcal{O}(n^3)\)。
Submission #69583581 - AtCoder Grand Contest 059
[AGC059D] Distinct Elements on Subsegments
给定一个长度为 \(n\) 的序列 \(b\) 和整数 \(k\),构造一个长为 \(n+k-1\) 的正整数序列 \(a\),满足 \(\forall 1\le i\le n\),\(b_i\) 等于 \(a_i,a_{i+1},\ldots,a_{i+k-1}\) 中不同的数的个数,或者报告无解。
\(n,k\le 2\times 10^5\)
首先需要满足 \(|b_i-b_{i+1}|\le 1\),我们考虑 \(b_i,b_{i+1}\) 之间的变化代表什么。设 \(l_i\) 表示 \(a_{i-k+1\sim i-1}\) 中是否所有数都和 \(a_i\) 不同,\(r_i\) 表示 \(a_{i+1\sim i+k-1}\) 中是否所有数都和 \(a_i\) 不同,那么有 \(b_i+l_{i+k}-r_i = b_{i+1}\)。所以如果 \(b_i\ne b_{i+1}\),我们就可以确定出 \(r_i,l_{i+k}\) 的值,否则只能确定 \(r_i=l_{i+k}\)。并且还有 \(\sum\limits_{i=1}^k l_i = b_1\),\(\sum\limits_{i=n-k+1}^n r_i = b_n\)。
考虑什么样的序列 \(l,r\) 是合法的,即存在至少一个 \(a\) 对应 \(l,r\)。我们求出 \(nex_i,pre_i\) 表示 \(a_i\) 的前驱、后继,发现知道了前驱后继就可以确定 \(l,r\),我们相当于知道了每个数前驱后继离自己的距离是否 \(<k\)。而因为前驱后继是一一对应的,所以如果某个 \(r_i = 0\),那么 \(l_{nex_i} = 0\),反之同理。所以 \(l\) 中的每个 \(0\) 和 \(r\) 中的 \(0\) 是一一对应的,并且假设 \(l_i\) 对应了 \(r_j\),则需要满足 \(1\le i-j < k\)。
所以我们一一对应的方式一定是 \(l\) 的第 \(i\) 个 \(0\) 匹配 \(r\) 的第 \(i\) 个 \(0\),否则交换了一定更优。设 \(pl_i,pr_i\) 表示 \(l,r\) 中第 \(i\) 个 \(0\) 的位置,则一组 \(l,r\) 合法的条件为 \(l,r\) 中 \(0\) 的个数相等,且 \(1\le pl_i-pr_i < k\)。因为限制条件都是两个值相等,所以 \(l,r\) 中 \(0\) 的个数是否相等是已经确定好了的。接下来我们要设置还没确定的位置使得尽可能满足条件。
假设对于某个 \(i\) 有 \(r_i = l_{i+k}\),如果 \(b_i = b_{i+1} = k\),那么一定有 \(r_i = l_{i+k} = 1\)。否则,将 \(r_i,l_{i+k}\) 全都设置为 \(0\) 一定不劣,因为此时中间至少有两个数相同,即至少一个 \(l\) 和 \(r\) 为 \(0\)。我们开始先将所有 \(0\) 都匹配上,那么将 \(r_i,l_{i+k}\) 设为 \(0\) 就是调整中间的一些匹配,原来满足条件的现在依然是满足条件的,而如果原来中间有不能匹配的现在就可能可以匹配了,所以这样做一定不劣。
于是我们直接将所有这样的 \(l_{i+k},r_i\) 设为 \(0\),而对于 \(b_1\),一定是将 \(1\sim b_1\) 设为 \(1\),因为这些位置前面的数不足 \(k\) 个,所以 \(0\) 越靠近中间越好,\(b_n\) 同理。设置完之后判断一下即可,最后构造就是从前往后枚举,如果有匹配的前驱就设为前驱,否则就设为一个新的数。复杂度 \(\mathcal{O}(n)\)。
Submission #69589075 - AtCoder Grand Contest 059
[AGC059E] Grid 3-coloring
有一个 \(n\times n\) 的矩阵,共有三种颜色,给定了最外面一层的颜色,求是否存在一种染色方案,使得相邻格子颜色不同。
\(n\le 2\times 10^5\)
神仙题。
矩阵存在一种染色方案,设 \(c_{i,j}\) 表示颜色,则我们一定能给每个格子赋一个整数权值 \(d_{i,j}\),满足 \(c_{i,j}\equiv d_{i,j}\pmod 3\),并且相邻两个格子权值相差 \(1\)。考虑证明,我们发现对于一种染色方案,只要确定了某个格子的权值,就能确定整个矩阵的权值。并且对于每个 \(2\times 2\) 的子矩阵,根据左上角的权值算出来的另外三个权值一定都满足限制,即如果左下角颜色等于右上角颜色,则右下角权值一定同时符合条件;如果左下角不等于右上角,则右下角权值一定等于左上角权值,且也符合条件。
于是问题就变成了是否存在一个合法的赋权值方案满足条件,我们首先设 \(d_{1,1}=c_{1,1}\),然后就可以算出整个外层的权值,先判断这个环的头尾的权值是否满足条件。接下来我们继续找必要条件,发现对于任意两个点 \((i,j),(i',j')\),这两个点的权值之差一定不超过它们的曼哈顿距离,即 \(|d_{i,j}-d_{i',j'}|\le |i-i'|+|j-j'|\)。而如果有这样的两个两个点不满足条件,一定是正方形的两条对边上,假设是左边和右边,我们将右边的点的横坐标设为左边点的横坐标,此时这个两个点依然不合法,所以只需要判断所有相对的两个点即可。
如果所有点都满足条件,那么一定有解,我们可以构造 \(d_{i,j} = \max\{d_{i,1}-(j-1),d_{i,n}-(n-j),d_{1,j}-(i-1),d_{n,j}-(n-i)\}\)。这样子最外层的点一定都满足条件,并且相邻两个点差不超过 \(1\),而且每个值的奇偶性都和 \(i+j\) 相同,所以一定有相邻两个格子权值差为 \(1\)。
Submission #69586467 - AtCoder Grand Contest 059
AGC058
[AGC058A] Make it Zigzag
skip。Submission #69761316 - AtCoder Grand Contest 058
[AGC058B] Adjacent Chmax
skip。Submission #69761873 - AtCoder Grand Contest 058
[AGC058C] Planar Tree
有一个 \(n\) 个顶点的圆环,每个点上有一个 \(1\sim 4\) 的权值 \(a_i\),保证 \(1\sim 4\) 的每个数都至少出现了一次。现在要在 \(n\) 个点间添加 \(n-1\) 条边使其构成一棵树,并满足以下要求:
- 如果一条边连接了两个点 \(x,y\),则必须满足 \(|a_x-a_y| = 1\)。
- 如果将所有边看成线段,那么任意两条线段不会在除端点外的地方相交。
判断是否有满足条件的方案。
\(n\le 3\times 10^5\)
首先我们可以将条件改为 \(|a_x-a_y|\le 1\) 就能连边,那么最后考虑某个权值相同的连通块,一定有一个点连向了一个权值不同的点,那么所有连通块内的点都连向这个点即可。于是我们就可以将所有相邻的权值相同的点合并起来。因为 \(|a_x-a_y|\le 1\) 就能连边,那么 \(1\) 能连向的权值 \(2\) 一定都可以连,所以如果有两个 \(1,2\) 相邻就可以将 \(1\) 删去,\(3,4\) 同理。
那么剩下的环一定是 \(\le 2\) 和 \(\ge 3\) 的点间隔排列。接下来考虑如下的性质:一棵合法的树一定存在一条原来环上相邻的两个点的边,满足其中一个点是叶子。证明可以手玩以下,那么答案一定可以通过每次连接相邻两个点并删去其中一个点的方式生成。因为剩下的点中连边一定是 \((2,3)\) 之间连,接下来考虑删去其中一个点之后会有什么影响。
如果删去了 \(3\),\(3\) 另一边无论是 \(1\) 还是 \(2\) 都可以和 \(2\) 合并,然后变成原来点数减 \(2\) 的问题。删去 \(2\) 同理,一定会恰好合并一个点。可以发现如果剩下的数全是 \(2,3\),那么一定可以合并完,所以我们每次要尽量删去 \(1,4\)。每次删去一个 \(2\) 最多会删去一个 \(4\),删去一个 \(3\) 最多会删去一个 \(2\),并且如果剩下 \(1,2,3,4\) 各一个是无解的,所以记 \(c_1,c_2,c_3,c_4\) 表示出现次数,一个必要条件是 \(c_2 > c_4,c_3 > c_1\)。可以发现这也是充要条件,因为每次都一定能找到一个符合条件的合并方法。
于是直接判断即可,复杂度为 \(\mathcal{O}(n)\)。
Submission #69764252 - AtCoder Grand Contest 058
[AGC058D] Yet Another ABC String
给定 \(a,b,c\),求有多少个由 \(A\) 个 a、\(B\) 个 b、\(C\) 个 c 组成的字符串 \(S\),满足 \(S\) 中不存在 abc、bca、cab 的子串。
\(a,b,c\le 3\times 10^6\)
牛逼题。
可以考虑直接去容斥,然后计算每个连续段的容斥系数,可以用三元生成函数来刻画。
或者考虑另一种方法,可以发现如果直接去容斥,那么两个钦定的位置可能有交,就不太好算。于是我们可以将条件转化为:不存在一个位置 \(i\) 满足,\(S_{i,i+1,i+2}\) 是 abc、bca、cab 中的一个子串,并且 \(i=1\) 或 \(s_{i-1,i,i+1}\) 不是其中的一个子串,可以发现如果 \(S\) 不合法的话,则一定存在这样一个 \(i\)。于是我们的容斥就变成了钦定一些位置 \(i\) 满足上述条件。
假设我们钦定了 \(k\) 个 \(i\) 不合法,考虑计算贡献,首先有个容斥系数 \((-1)^k\)。可以发现,两个钦定的位置的子串位置一定不会重叠,于是我们考虑先将这些钦定的子串拿出来,最后再插进去。那么剩下的字符可以任意排列,方案数为 \(a+b+c-3k\choose a-k,b-k,c-k\)。
如果我们要将一个长度为 \(3\) 的子串插到某个字符后面,比如 a,那么只有 abc、cab 合法,而 bca 不合法。另外两个字母同理,即一定恰好有两种方法。所以方案数可以分是否插到了最开头两种情况考虑,如果没有子串插到开头,那么就是将 \(k\) 个球放到 \(a+b+c-3k\) 个盒子中,并且还有贡献 \(2^k\)。如果有子串插到了开头,那么就是 \(k-1\) 个球放到 \(a+b+c-3k+1\) 个盒子中,还有贡献 \(3\times 2^{k-1}\),所以答案就是:
复杂度 \(\mathcal{O}(n)\)。
Submission #69767314 - AtCoder Grand Contest 058
[AGC058E] Nearer Permutation
对于两个 \(1\sim n\) 的排列 \(p,q\),定义 \(d(p,q)\) 表示通过交换 \(p\) 的相邻两个元素变为 \(q\) 的最小操作次数。设 \(I\) 表示 \(I_i=i\) 的排列,定义 \(f(p)\) 为所有满足 \(d(p,q)\le d(q,I)\) 的排列 \(q\) 中,字典序最小的 \(q\)。现在给定一个排列 \(q\),求是否存在一个排列 \(p\) 满足 \(f(p)=q\)。
\(n\le 3\times 10^5\)
先考虑给定一个 \(p\),怎么求 \(f(p)\)。因为要字典序最小,所以我们依次枚举 \(i\) 从 \(1\sim n\),每次考虑 \(q_i\) 最小填多少。假设 \(q_i=x\),我们要尽量让后面的 \(d(p,q)\le d(q,I)\),最优方式一定是直接将 \(p\) 中的 \(x\) 移到最开头,而每次移动都会让 \(d(p,q)\) 加一,\(d(q,I)\) 减一。于是设 \(s=\frac{inv(p)}2\),假设排列下标从 \(0\) 开始,那么每次操作为:
- 找到 \(p_{0,\ldots,\min(\lfloor s\rfloor,n-1)}\) 中最小的 \(p_i\),将 \(p_i\) 从 \(p\) 中删除并加到 \(q\) 末尾,然后将 \(s\) 减去 \(i\)。
接下来注意到,每次 \(s\) 都是不增的,那么 \([0,\min(s,n-1)]\) 的范围就会在减少,并且每次都移除了最小值,那么 \(q_i\) 应该都是递增的。于是我们找到第一个 \(k\) 满足 \(q_k>q_{k+1}\)(如果没找到那么 \(q=I\),当 \(p=I\) 时有 \(f(p)=q\)),设在做了 \(k\) 次操作后的序列为 \(a\),一定有:
- \(a_0=q_k\),并且 \(a_0\) 是 \(a_{0,\ldots,s}\) 中的最小值,且 \(a_{s+1} = q_{k+1}\)。
那么此时删掉 \(q_k\) 后一定会删掉 \(q_{k+1}\),并且这是唯一一种可能出现 \(q_k>q_{k+1}\) 的情况。可以发现,\(a\) 中剩下的数每次都会删掉最开头的数,相当于按原顺序排列。于是做了 \(k\) 次后的序列一定长成:\(q_k,q_{k+2},q_{k+3},\ldots,q_{x},q_{k+1},q_{x+1},\ldots,q_{n}\)。
那么我们考虑倒着做操作,即令 \(p=q\),然后依次枚举 \(q_{k+1},q_{k-1},q_{k-2},\ldots,q_1\),每次将当前的 \(q_i\) 向后移动 \(c_i\) 个位置。现在就是要求一组 \(c_i\),考虑怎么判断 \(c_i\) 是否合法,设在执行 \(k+1\) 次操作后,\(\Delta\) 为 \(q_{k+1}\) 的位置与 \(s\) 的差,那么我们需要保证 \(\Delta\in\{0,\frac 1 2\}\)。可以发现,\(c_i\) 每增加 \(1\),都会让 \(inv(p)\) 增加 \(1\),如果 \(i\ne k+1\),就会让最后的 \(s\) 减一,否则就会让 \(q_{k+1}\) 加一,即都会让 \(\Delta\) 减去 \(\frac 1 2\)。
于是,\(c_i\) 每增加 \(1\) 都会让 \(\Delta\) 减少 \(\frac 1 2\),当 \(c_i\) 都为 \(0\) 时有 \(\Delta = \frac{inv(q)}{2}\),而 \(\Delta\) 应该为 \(0\) 或 \(\frac 1 2\),于是 \(\sum c_i\) 应该为 \(inv(q)\) 或 \(inv(q)-1\),我们可以分别判断这两种情况。因为知道了 \(\sum c_i\),于是就知道 \(inv(p)=inv(q)+\sum c_i\),那么此时的最优策略一定是依次枚举 \(q_1,q_2,\ldots,q_{k-1},q_{k+1}\),求出它们 \(c_i\) 最大能取到多少。
因为我们知道了 \(inv(p)\),相当于知道了 \(s=\frac{inv(p)} 2\),就可以模拟每次操作了。设 \(res\) 表示剩下的 \(\sum c_i\),则一定有 \(res\le s\),那么每次操作要么是移到序列末尾,要么是将 \(res\) 减为 \(0\),所以剩下的数的相对位置不会发生变化,只需记录 \(pos_i\) 表示 \(q\) 中 \(i\) 的位置即可 \(\mathcal{O}(n)\) 判断。总复杂度为 \(\mathcal{O}(n\log n)\),瓶颈在于求 \(inv(q)\)。具体细节可以参考代码。
Submission #69899786 - AtCoder Grand Contest 058
[AGC058F] Authentic Tree DP
对于一棵大小为 \(n\) 的无根树 \(t\),定义 \(f(t)\) 为:
- 如果 \(n=1\),则 \(f(t) = 1\)。
- 否则,对于 \(t\) 中的每条边 \(e\),设删掉 \(e\) 后得到的两棵树分别为 \(t_1(e)\) 和 \(t_2(e)\),则 \(f(t) = \frac 1 n \sum\limits_{e\in t}f(t_1(e))f(t_2(e))\)。
给定一棵大小为 \(n\) 的树 \(t\),求 \(f(t)\)。对 \(998244353\) 取模。
\(n\le 5000\)
神仙问号题。
如果把 \(\frac 1 n\) 改成 \(\frac{1}{n-1}\),那么可以直接用归纳法证明 \(f(t)=1\),我们考虑一个组合意义,相当于给每条边赋一个边权,然后每次枚举了所有边权中的最大值是哪条边。那么 \(\frac{1}{n-1}\) 相当于是枚举了每个边权顺序的排列,答案为 \(1\)。但现在系数是 \(\frac 1 n\),只考虑边没什么前途,我们可以考虑给每个边上面加一个点,原来 \((u,v)\) 的边现在变成了 \((u,p),(p,v)\),我们记这些新加的点为边点。
此时给每个点赋一个点权,然后再枚举点权最大值是哪个点(一定得是边点),那么此时系数就变成了 \(\frac{1}{2n-1}\),但我们想要的系数是 \(\frac 1 n\)。于是考虑非常牛的一步,我们在每个边点下面添加 \(-1\) 个叶子节点,或者说添加 \(p-1\) 个叶子节点(\(p\) 为模数),那么再做上述问题,前面的系数就变为了 \(\frac{1}{2n-1+(n-1)(p-1)}\),对 \(p\) 取模后正好就是 \(\frac 1 n\)!
然后我们进一步转化问题,一个排列合法当且仅当每一步时最大值都在某个边点上,即边点上的权值要大于所有相邻点的权值。于是问题就变为了,给定一棵树,将某个边点下面挂 \(p-1\) 个叶子,求一个排列满足边点权值大于所有相邻点的权值的概率。大于关系如下图所示:

此时仍然不是很好计数,于是套路的考虑容斥,我们钦定一些向上指的边不满足条件,其他向上指的边任意,那么此时所有边都是向上指的,那么一个大小为 \(S\) 的连通块的贡献就是 \(\frac 1 S\)。于是设 \(f_{u,i}\) 表示 \(u\) 子树内,有 \(i\) 个点指向了 \(u\),那么转移就是一个卷积的形式。但还要考虑边点的贡献,如果 \(u\) 由某个 \(f_{v,j}\) 连过来,那么这个边点相当于有 \(j+(p-1)+1\) 个点指向它,那么贡献为 \(\frac 1 j\)。复杂度为树上背包,即 \(\mathcal{O}(n^2)\)。
Submission #69903945 - AtCoder Grand Contest 058
AGC057
[AGC057A] Antichain of Integer Strings
skip。Submission #69793646 - AtCoder Grand Contest 057
[AGC057B] 2A + x
给定一个长度为 \(n\) 的数列 \(a\) 和正整数 \(x\),每次你可以选择一个 \(i\),然后令 \(a_i\larr 2a_i+x\),求在任意次操作后 \(a\) 的极差最小是多少。
\(n\le 10^5,a_i,x\le 10^9\)
先将 \(a_i\) 排序,首先不可能出现 \(a_n\) 操作过但某个 \(a_i\) 没操作过的情况,不然 \(a_n\) 不操作一定更优。那么要么就是 \(a_n\) 没操作过,要么就是整个序列都操作过。如果都操作过,考虑所有数同时进行操作,如果操作前序列的极差 $ < x$,那么若干次操作后就可以变为 \(0\),否则不操作一定更优。
于是只需要求出 \(a_n\) 不操作极差最小是多少,那么求出每个 \(a_i\) 能否得到 \(a_n\),如果不能就求出操作时离 \(a_n\) 最接近的两个数 \(l_i,r_i\) 是多少。于是问题就是在每个 \(l_i,r_i\) 中选一个,求最小极差,将 \(l_i\) 排序,枚举 \(l\) 的最小值即可。复杂度 \(\mathcal{O}(n\log n)\)。
Submission #69793927 - AtCoder Grand Contest 057
[AGC057C] Increment or Xor
给定 \(n\) 和一个 \(0\sim 2^n-1\) 的排列 \(a_0,\ldots,a_{2^n-1}\),你每次可以执行以下两种操作:
- 对所有 \(i\),执行 \(a_i\larr (a_i+1)\bmod 2^n\)
- 选择一个 \(x\),对所有 \(i\),执行 \(a_i\larr a_i\oplus x\)
判断能否通过若干次操作使得所有 \(a_i=i\),如果可以,还需要构造一种操作数不超过 \(10^6\) 的方案。
\(n\le 18\)
考虑又有 \(+1\) 又有异或,于是我们在反 trie 上考虑。将所有数插到反 trie 中,就是一棵深度为 \(n\) 的满二叉树,记 \(tr_i\) 表示 \(i\) 二进制反过来的数,\(pos_i\) 表示 \(i\) 在 \(a\) 中的位置。于是我们的目标是将 \(pos_{tr_i}\) 变为 \(tr_i\),\(+1\) 操作就是对最右边一条链上的所有点依次做交换左右儿子,异或操作就是对一层的所有点做交换左右儿子,不妨设为从 \(p_i\) 变为 \(q_i\)。
于是我们可以建出 \(p_i\) 和 \(q_i\) 的 trie 树,对于根节点,要么 \(p\) 的左子树与 \(q\) 的左子树集合相同,要么 \(p\) 的左子树与 \(q\) 的右子树集合相同,然后继续递归到每个节点判是否满足条件,并且也能求出每个节点是否发生交换。然而现在一次 \(+1\) 操作只能给最右边的链的每个点执行交换,于是我们可以将每个 \(+1\) 前面和后面都加上一个 \(\oplus x\),这样子就是任选一条路径进行交换。
那么现在两种操作就变成了任选一条路径进行交换,或者选一层所有点进行交换,那可以发现这两种操作与原问题是等价的,因为对于每一种方案,我们都可以让 \(\oplus x,+1\) 变为 \((\oplus x,+1,\oplus x),\oplus x\)。那么我们设 \(tp_i\) 表示节点 \(i\) 是否需要进行交换操作,每次就是路径异或,或者同一层异或。于是我们依次枚举最后一层需要交换的点,将根到这个点的路径进行异或,最后再看每一层的点状态是否一致即可。
操作次数最多为 \(3\times 2^{n-1}+1\),显然不超过 \(10^6\)。
Submission #69800556 - AtCoder Grand Contest 057
[AGC057D] Sum Avoidance
给定一个数 \(S\),称一个正整数集合 \(A\) 是好的,当且仅当 \(A\) 满足每个数都在 \([1,S)\) 内,且不能通过 \(A\) 中的数凑出 \(S\)。考虑在 \(A\) 元素最多的前提下字典序最小的 \(A\),求集合 \(A\) 中第 \(k\) 小的数是多少,或报告不存在。
多组询问。\(T\le 1000,S\le 10^{18}\)
引理 1:\(|A| = \lfloor\frac{S-1} 2\rfloor\)。
证明:我们考虑任何一对 \((i,S-i)\),这两个数中最多只有一个数会被选,如果 \(S\) 是偶数,那么还有 \(\frac S 2\) 不能选。于是 \(A\) 有一个上界 \(\lfloor\frac{S-1} 2\rfloor\)。然后如果我们选择 \(\lfloor\frac{S-1} 2\rfloor+1\sim S\) 中的所有数,这显然是一个合法的集合。于是我们就证明了 \(A\) 的上界,并且构造出了一组合法解。
所以 ,最终的答案集合中,一定是每对 \((i,S-i)\) 中恰好有一个数出现在集合中。现在,我们设集合 \(B\) 为最终的答案集合,\(A = \{x|x\in B,x\le \lfloor\frac{S-1} 2\rfloor\}\),那么我们可以通过集合 \(A\) 来推出 \(B\)。
引理 2:若集合 \(A\) 中的一些数相加能得到 \(x\),且 \(x\le \lfloor\frac{S-1} 2\rfloor\),则 \(x\in A\)。
证明:假设 \(x\notin A\),则 \(S-x\in B\),因为 \(A\) 中的数可以凑出 \(x\),又有一个数 \(S-x\),那么就能凑出 \(S\) 了,所以 \(x\) 必须在集合 \(A\) 中。
引理 3:若 \(A\) 中的数不能凑出 \(S\),那么 \(B\) 一定也不能凑出 \(S\)。
证明:假设 \(A\) 中的数不能凑出 \(S\),\(B\) 中的数能凑出 \(S\),那么这些凑出 \(S\) 的数中一定有一个是 \(> \lfloor\frac{S-1} 2\rfloor\),假设为 \(x\),这就意味着还存在一些数能凑出 \(S-x\),但是根据引理 2,\(S-x\le \lfloor\frac{S-1} 2\rfloor\),应该要加入集合 \(A\),矛盾。
根据引理 3,我们只需要求出集合 \(A\) 的最小字典序,就等同于求出了答案 \(B\)。这样有个好处就是 \(A\) 没有大小的限制,所以要求字典序最小,策略一定是从小到大看每个数能不能加入集合 \(A\),能加就加。考虑第一个应该加入的数是什么,假设这个数为 \(d\),根据上面的策略,显然就是第一个不是 \(S\) 的因数的数。根据直觉,这个数应该不会太大,实际上当 \(S\le10^{18}\) 时,\(d\le 43\)。
接下来我们把加入的数分为两类,第一类是能被 \(A\) 的数表示出来,第二类是加入了这个数后剩下的数仍然不能凑出 \(S\),应该贪心加入。从 \(\bmod d\) 的剩余系角度考虑,如果一个数是以第二类加入的,那么这个数一定和之前的数都不同余,所以以第二类加入的数不超过 \(d\) 个。于是我们可以求出 \(\bmod d\) 的同余最短路。
我们设 \(f_i\) 表示能凑出的最小的 \(\bmod d=i\) 的数,第一类情况加入的数不会对数组产生影响,于是只需要考虑第二类数是哪些,我们每次找出下一个最小的以第二类加入的数。考虑一个 \(v\) 能以第二类数加入的条件,设 \(x=v\bmod d\),首先应该有 \(v < f_{x}\),其次就是在更新完整个数组后应该满足 \(f_{S\bmod d} > S\)。
如果加入了一个 \(v\),那么最多会使用 \(d-1\) 个 \(v\) 来更新数组,因为 \(d\) 个 \(v\) 可以用 \(v\) 个 \(d\) 来代替。所以有更新:\(f_{(u+ix)\bmod d}\larr f_u+iv\),因为要让 \(f_{S\bmod d} > S\),有 \(f_{(S-ix)\bmod d} > S-iv\),即 \(v > \lfloor\frac{f_{(S-ix)\bmod d}} i\rfloor\)。于是我们能求出所有 \(\bmod d = x\) 的数中最小的能以第二类数加入的 \(v\) 是多少,即 \(v_x = \max\limits_{0\le i < d}\lfloor\frac{f_{(S-ix)\bmod d}} i\rfloor+1\)。那么这一次应该加入的数就是 \(\min v_x\)。
重复 \(d\) 次上述操作,即可确定最终的 \(f\)。然后要求出第 \(k\) 小的数,可以二分答案,求出一个 \(x\) 的排名,然后看与 \(k\) 的大小关系进行二分即可,最终时间复杂度 \(\mathcal{O}(T(d^3+d\log V))\)。
Submission #69795531 - AtCoder Grand Contest 057
[AGC057E] RowCol/ColRow Sort
给定一个 \(n\times m\),值域 \([0,9]\) 的矩阵 B,求有多少个 \(n\times m\) 的矩阵 A,满足:
- 分别对 A 的 每一列 中元素从小到大排序,再分别对 A 的 每一行 中元素从小到大排序能够得到 B。
- 分别对 A 的 每一行 中元素从小到大排序,再分别对 A 的 每一列 中元素从小到大排序能够得到 B。
\(n,m\le 1500\)
首先思考只有 \(0,1\) 怎么做,设 \(a_i\) 表示第 \(i\) 行 \(0\) 的个数,\(b_j\) 表示第 \(j\) 列 \(0\) 的个数。那么先对行排序,就是将每行的 \(a_i\) 个 \(0\) 放到左边,再对列排序就是将 \(a_i\) 从大到小排序。先对列,再对行排序就是将 \(b_j\) 从大到小排序。于是一个矩阵 A 合法,当且仅当它的 \(a_i\) 构成的可重集与 B 的 \(a_i\) 的可重集相等,A 的 \(b_j\) 构成的可重集与 B 的 \(b_j\) 相等。
进一步可以发现,如果知道了 A 的所有 \(a_i,b_j\),那么我们一定可以确定 A 是什么。因为排序后是个杨表结构,于是我们一定可以通过,依次从大到小枚举 \(a_i\),此时一定恰好有 \(a_i\) 个 \(b_j > 0\),将这些位置填上 \(1\),然后将这些 \(b_j\) 减一,一直做下去来唯一确定 A。所以一个矩阵 A 合法,当且仅当存在两个排列 \(p_i,q_j\),使得 \(\forall i,j,A_{i,j}=B_{p_i,q_j}\)。那么答案就是两个可重集的排列数相乘,即:
然后考虑值域为 \([0,9]\) 怎么办,还是先看怎么判合法。我们枚举 \(k\in[0,9]\),每次将 A 和 B 中 \(<k\) 的数设为 \(0\),\(\ge k\) 的数设为 \(1\),然后看这两个 01 矩阵是否合法。如果对于每个 \(k\) 都合法,那么矩阵 B 就合法。于是条件就是存在一组排列 \((p_0,q_0,p_1,q_1\ldots,p_9,q_q)\),满足 \(\forall 0\le k\le 9,1\le i\le n,1\le j\le m,[A_{i,j}\le k] = [B_{p_{k,i},q_{k,j}}\le k]\)。
上述条件的必要性显然,充分性考虑我们枚举 \(k\),每次将 A 的 01 矩阵相较于上一次多出来的 \(0\) 的部分的值设为 \(k\),于是这一组排列就一定能对应一个合法 \(A\)。因为存在一组排列这个条件不好做,我们还是考虑去计数有多少组排列满足条件,最后对每个 \(k\),除以重复的方案数(和上面的可重集计数一样)。
现在考虑计数有多少组排列,依次枚举 \(k\),现在问题是知道了上两个排列 \(p_{k-1},q_{k-1}\),求现在有多少个排列 \(p_k,q_k\)。那么思考 \(p_k,q_k\) 应该满足哪些条件,因为 A 中在 \(k-1\) 是 \(0\) 的位置在 \(k\) 时也必须是 \(0\),也就是说 \(A_{i,j} < k\Rightarrow A_{i,j}\le k\),在 B 中就是 \(B_{p_{k-1,i},q_{k-1,j}} < k\Rightarrow B_{p_{k,i},q_{k,j}}\le k\)。于是问题就是给定两个排列 \(p',q'\),求有多少个排列组 \((p,q)\),满足 \(\forall B_{p'_i,q'_j} < k,B_{p_i,q_j}\le k\)。显然 \(p',q'\) 具体是什么不重要,只需要知道和 \(p'^{-1}\times p,q'^{-1}\times q\) ,即两组排列的相对关系即可。所以我们可以直接钦定 \(p'_i=i,q'_j=j\),计数 \((p,q)\) 满足 \(\forall B_{i,j} < k,B_{p_i,q_j}\le k\)。
因为 B 中 \(\le k\) 的部分是一个杨表结构,所以一个位置小于一个数的条件可以简化。设 \(a_i\) 表示 B 的第 \(i\) 行中最后一个 \(<k\) 的位置,\(b_j\) 表示 B 的第 \(j\) 列中最后一个 \(\le k\) 的位置。于是条件就是 \(\forall j\le a_i,p_i\le b_{q_j}\)。因为 \(b\) 是递减的,那么对于一个 \(i\),条件最严的肯定是 \(q_j\) 最大的。所以改写条件为 \(p_i\le b_{\max\limits_{j=1}^{a_i} q_j}\)。现在考虑计数 \(c_i=\max\limits_{j=1}^{a_i} q_j\),如果我们求出了 \(c_i\),那么可以分别算出有多少个 \(p,q\)。
对于 \(p\),有 \(p_i\le b_{c_i}\) 的限制,因为 \(a_i\) 递减,所以 \(\max\limits_{j=1}^{a_i} q_j\) 递减,又因为 \(b\) 递减,所以 \(b_{c_i}\) 递增。所以 \(p\) 的个数为 \(\prod\limits_{i=1}^n b_{c_i}-i+1\)。
对于 \(q\),我们枚举每个 \(i\),如果 \(c_i=c_{i-1}\),那么说明在 \((a_i,a_{i-1}]\) 中没有出现最大值,那么前 \(a_i\) 个数一定有一个是最大值 \(c_i\),于是 \((a_i,a_{i-1}]\) 中第一个数有 \(c_i-1-(a_i-1)=c_i-a_i\) 种选法,第二个数有 \(c_i-a_i-1\) 种选法,一直下去,可以得出贡献为 \(\frac{(c-a_i)!}{(c-(a_{i-1}-a_i))!}\)。
如果 \(c_i < c_{i-1}\),那么说明最大值在 \((a_i,a_{i-1}]\) 中,每个位置是最大值是等价的,类似的我们可以算出贡献为 \((a_{i-1}-a_i)\times \frac{(c-a_i-1)!}{(c-(a_{i-1}-a_i))!}\)。
于是我们可以 dp,设 \(f_{i,j}\) 表示前 \(i\) 个数,\(c_i=j\) 的方案数。转移时发现贡献与 \(j\) 无关,所以可以直接前缀和优化,做到 \(\mathcal{O}(n^2)\) 的复杂度。我们对每个 \(k\) 都这么做一遍,把答案乘起来,最后除以系数即可。总复杂度 \(\mathcal{O}(10n^2)\)。
Submission #65155644 - AtCoder Grand Contest 057
[AGC057F] Reflection
数轴上有三个点 \(A,B,C\),坐标分别为 \(a,b,c\),满足 \(a\le b\le c\),每次可以进行如下两种操作之一:
- 将点 \(A\) 关于点 \(B\) 对称。
- 将点 \(C\) 关于点 \(B\) 对称。
每次操作后,按坐标从小到大的顺序重新给每个点标注 \(A,B,C\)。求经过任意次操作后,能得到多少个不同的三元组 \((a,b,c)\)。
答案对 \(998244353\) 取模。多组数据,\(T\le 10^5,-10^{18}\le a,b,c\le 10^{18}\)
记 \(AB\) 间距离为 \(x\),\(BC\) 间距离为 \(y\),显然一组询问的答案只和 \(x,y\) 有关。我们将计数三元组 \((a,b,c)\) 的个数,改为计数三元组 \((b,x,y)\) 的个数。考虑某个 \((b,x,y)\) 经过一次操作可能得到什么,如果 \(x\le y\),那么两种操作分别会得到 \((b+x,x,y-x)\) 和 \((b-x,y-x,x)\);如果 \(x > y\),那么两种操作分别会得到 \((b+y,y,x-y)\) 和 \((b-y,x-y,y)\)。
可以发现,\(x,y\) 每次相当于在进行辗转相减,所以总的状态数是有限的,现在考虑计数有多少不同的三元组 \((b,x,y)\)。因为每次辗转相减得到的 \((x,y)\) 都是不一样的,所以我们只需要考虑进行了相同辗转相减次数的三元组,此时无序对 \((x,y)\) 一定是相同的。我们先只考虑 \(x>0,y>0,x\ne y\) 的情况,那么 \(b\) 每次都会选择加上或减去 \(\min(x,y)\)。
我们记录每次辗转相减的 \(\min(x,y)\),例如 \((10,7)\) 就是 \(7,3,3,1,1,1\)。现在考虑某个前缀,我们要给每个数确定正负号然后求和,也就是选出一个选择正号的集合,那么两个三元组的 \(b\) 不同也就是选出的集合的元素之和不同。并且可以发现,\(x,y\) 间的顺序只和最后一个数选择的正负号有关,也就是说两个三元组不同当且仅当在前缀中选出来的集合元素和不同,或者最后一个数是否被选的状态不同。
设我们记录的数组为 \(a_1,\ldots,a_m\),设 \(s_i\) 表示 \(a_1,\ldots,a_i\) 中不同的集合元素和有多少个。那么对于所有 \(i<m-1\),要在前 \(i\) 个数中选择一个集合,使得元素和不同或第 \(i\) 位状态不同,求方案数。我们先在前 \(i-1\) 个数中选择一个集合,然后确定第 \(i\) 位是否选,答案就是 \(2s_{i-1}\)。
接下来考虑边界情况,如果 \(i=m-1\),那么这个时候 \(x=y\),不考虑 \(x,y\) 之间的顺序,也就是说我们两种选法不同当且仅当元素和不同,方案数为 \(s_{m-1}\)。如果 \(i=m\),那么 \((x,y) = (\gcd(a,b),0)\),因为我们后面还能自己选择交换 \(x,y\),所以还是不考虑 \(x,y\) 间的顺序,最后将答案乘 \(2\),即 \(2s_m\)。所以总的答案就是 \(1+2s_0+2s_1+\ldots+2s_{m-3}+s_{m-1}+2s_m\),注意在一开始特判 \(a,b\) 中有 \(0\) 或 \(a=b\) 的情况。
我们可以先考虑如何求某个 \(s_p\)。观察序列 \(a\),因为是辗转相减,所以 \(a\) 一定可以划分为 \(\mathcal{O}(\log V)\) 个连续段,假设有 \(k\) 个,第 \(i\) 个连续段的数为 \(v_i\),长度为 \(c_i\)。观察辗转相减的性质可以发现,\(\forall 1\le i \le k-2\),有 \(v_i = c_{i+1}v_{i+1}+v_{i+2}\),即每个连续段的数等于下一段所有数再加上下下段开头的数的和。考虑将每个不同的能凑出来的数唯一对应到某个集合上然后对集合计数。
如果存在某一段的数全部选了且下一段至少选了一个数,并且前面一段没有选完,那么就可以将这一段和下一段的一个数删去,并在上一段选一个数,即合并操作。称一个集合合法当且仅当这个集合每一段选的数都是一段前缀,并且不能再发生合并,也就是说,如果存在一段的数全选了,下一段至少选了一个数,那么上一段就也应该全选,同理这段之前的所有段都要全选。如果我们选择的前缀 \(p\) 满足 \(p<m\),可以证明每个合法的集合的元素和都不同,即 \(s_p\) 就等于合法的集合数。
对于两种不同的选法,它们的元素和的大小关系,等价于比较两种选法在每个段中选的个数的字典序。因为两个集合都合法,所以对于任意一段,其后面选的所有数加起来也没有这段数大,可以从后往前归并考虑,也就是说任意两个不同的合法集合元素和都不同。于是我们就可以 dp 了,设 \(f_{i,0/1/2}\) 表示前 \(i\) 段,第 \(i\) 段没选满/第 \(i\) 段选满了但前面没选满/前 \(i\) 段都选满了的方案数,那么 \(f_{i,1}\) 后面的段就不能选任何数。
转移是容易的,我们有 \(f_{i,2}\) 恒为 \(1\),\(f_{i,0} = c_i(f_{i-1,0}+f_{i-1,2})+f_{i-1,1}\),\(f_{i,1} = f_{i-1,0}\)。一直转移到 \(p\) 所在段即可,答案为此时的 \(f_{i,0}+f_{i,1}+f_{i,2}\)。现在考虑求原答案,可以将原答案写成 \(3+2\sum\limits_{i=1}^{m-1} s_i - 2s_{m-2}-s_{m-1}+2s_m\),而 \(\sum\limits_{i=1}^{m-1} s_i\) 也是容易计算的,我们可以在处理每段时,将 \(c_i\) 分别设为 \(1\sim c_i\),然后再将此时的 \(f_{i,0}+f_{i,1}+f_{i,2}\) 贡献给答案。即:
\(s_{m-2},s_{m-1}\) 也可以同理计算,最后一个问题是如何计算 \(s_m\),因为这个时候如果我们把最后一段 \(v_k\) 全选完但前面没选满时依然合法,但最后一段 \(v_k\) 可以合并到一个 \(v_{k-1}\)。考虑 \(s_m\) 比 \(s_{m-1}\) 多了哪些集合,可以发现只有当 \(m\) 个数全选时前 \(m-1\) 个数才凑不出,所以 \(s_m = s_{m-1}+1\)。至此我们解决了所有问题,总复杂度为 \(\mathcal{O}(T\log \max(x,y))\)。
Submission #70889268 - AtCoder Grand Contest 057
AGC056
[AGC056A] Three Cells per Row and Column
skip。Submission #70147916 - AtCoder Grand Contest 056
[AGC056B] Range Argmax
给定 \(n\) 和 \(m\) 个区间 \([l_i,r_i]\),设一个 \(1\sim n\) 的排列 \(p\) 生成的 \((x_1,\ldots,x_m)\) 序列为:对于每个 \(i\in [1,m]\),\(x_i\) 为 \(a_{l_i,\ldots,r_i}\) 中最大值的下标。求有多少种可能的 \(x\) 序列,答案对 \(998244353\) 取模。
\(n\le 300\)
好题。
不好计数 \(x\) 序列,考虑将 \(x\) 序列唯一对应到一个排列 \(p\) 上,然后去计数符合要求的 \(p\) 序列。我们枚举 \(i\) 从 \(n\) 到 \(1\),每次将 \(i\) 填到能填到的最左边的位置,来唯一对应到一个排列 \(p\) 上。
接下来考虑计数 \(p\),我们依次填 \(n\sim 1\),首先看 \(n\) 填到什么位置。如果 \(n\) 填到了某个 \(a_i\) 上,因为要求能填左边就要尽量填左边,所以 \(a_i\) 要大于 \(a_{1\sim i-1}\) 中的所有数,不然 \(a_i\) 与这个位置交换也合法就不满足条件。要让 \(a_i\) 大于其左边所有数,相当于这个大于关系可以传到 \(a_1\),
假设包含 \(a_i\) 的区间中左端点最小的是 \(l\),那么我们已经满足 \(a_i>a_{l\sim i-1}\),接下来还要继续传递,那么一定要让 \([1,i-1]\) 中的最大值位置 \(\ge l\),假设为 \(j\),我们又可以找到所有包含 \(j\) 的区间中左端点最小的是多少,并继续传递下去。
于是可以考虑区间 dp,设 \(f_{l,r,k}\) 表示考虑区间 \([l,r]\),且 \([l,r]\) 中最大值的位置 \(\ge k\) 的方案数,转移时分最大值是 \(=k\) 还是 \(>k\)。设 \(g_{l,r,k}\) 表示所有在 \([l,r]\) 内且包含 \(k\) 的区间左端点最小是多少,如果由 \(>k\) 转移就是 \(f_{l,r,k+1}\),如果 \(=k\) 就相当于要求 \([l,k-1]\) 中最大值位置 \(\ge g_{l,r,k}\),\([k+1,r]\) 中没有限制。所以转移为:
最终答案为 \(f_{1,n,1}\)。复杂度为 \(\mathcal{O}(n^3)\)。
Submission #68977693 - AtCoder Grand Contest 056
[AGC056C] 01 Balanced
构造一个长度为 \(n\) 的 01 字符串,满足 \(m\) 个条件,每个条件给出一个长度为偶数的区间 \([l,r]\),要求区间内 \(0\) 和 \(1\) 的数量相同,求出字典序最小的字符串。
\(n\le 10^6,m\le 2\times 10^5\)
显然 \(0101\ldots\) 满足所有条件,所以一定有解。
考虑差分约束,可以设 \(s_i\) 表示 \(1\sim i\) 中 \(0\) 的个数,但是这样边权会有负数,跑 SPFA 复杂度不太能接受。于是我们换一种定义,将 \(0\) 赋为 \(1\),\(1\) 赋为 \(-1\),设 \(s_i\) 表示前缀和,那么每个条件的连边就变为了 \(l-1\xrightarrow{0}r,r\xrightarrow{0}l-1\),边权就没有负数了。但是我们还有条件 \(s_i-s_{i-1}\in \{-1,1\}\),这个条件用差分约束不太好刻画。
我们不妨设条件为 \(-1\le s_i-s_{i-1}\le 1\),于是连边就是 \(i-1\xrightarrow{1}i,i\xrightarrow{1}i-1\),然后跑最短路。因为边权只有 \(01\),所以直接用 01bfs 即可。考虑最后建出来的图,我们将 \(i\) 为偶数和奇数的点分为两边,发现边权为 \(1\) 的边都是在两侧之间连,而边权为 \(0\) 的边都是在同一侧之间,也就是说每一条到 \(i\) 的路径边权和都与 \(i\) 同奇偶,那么就不可能出现 \(s_i-s_{i-1}=0\) 的情况。
最后 \(s_i=[dis_i<dis_{i+1}]\),复杂度为 \(\mathcal{O}(n+m)\)。
Submission #57897173 - AtCoder Grand Contest 056
[AGC056D] Subset Sum Game
给定一个长度为 \(n\) 的序列 \(a\),保证 \(n\) 为偶数。Alice 和 Bob 轮流操作,Alice 先手,每次当前操作的人选择一个 \(a\) 中还未被删去的数删去。最终如果 Alice 选择的所有数的和 \(\in [l,r]\),则 Alice 获胜,否则 Bob 获胜。求双方都采取最优策略时谁会获胜。
\(n\le 5000,a_i\le 10^9\)
将 \(a\) 排序,我们可以先考虑 Bob 先手时谁会获胜。
Bob 可以选择让 Alice 选的数尽量小或者尽量大,如果 Bob 一开始的目标为让 Alice 选择的所有数和最小,那么每次 Bob 一定是选择还未被删去的数中最大的数。双方轮流操作下去,则 Alice 选的数之和最大可能为为 \(a_1+a_3+\ldots+a_{n-1}\),如果这个数 \(<l\),相当于 Alice 尽力让自己选的数最大但还是到不了 \([l,r]\),那么 Bob 采取上述策略一定可以获胜。同理,如果 \(a_2+a_4+\ldots+a_n > r\),也是 Bob 获胜。
否则,如果 \(a_1+a_3+\ldots+a_{n-1}\ge l\) 且 \(a_2+a_4+\ldots+a_n \le r\),我们将序列分组为 \((a_1,a_2),(a_3,a_4),\ldots,(a_{n-1},a_n)\),那么从每组任选一个数的和都在 \([l,r]\) 之间,于是 Bob 每次选一个数,Alice 都选组内另一个数即可获胜。于是这就是 Alice 获胜的充要条件。
接下来考虑 Alice 先手,我们先枚举 Alice 第一次选哪一个数,就变成了 Bob 先手。然后在接下来的 \(n-1\) 中,如果 Alice 能找到一个长度为 \(n-2\) 的子序列,满足这个序列奇数位和 \(\ge l\) 且偶数位和 \(\le r\),那么一定是 Alice 获胜,策略同上,即使 Bob 选择剩下的那个数也不影响。接下来我们要说明,如果不满足这个条件,那么一定是 Bob 获胜。
如果不满足上述条件,相当于对于任意一个长度为 \(n-2\) 的子序列,都满足奇数位和 \(<l\) 或偶数位和 \(>r\)。考虑删去 \(n-1\) 个数中每个数形成的子序列,那么满足奇数位和 \(<l\) 的一定是一段前缀,满足偶数位和 \(>r\) 的一定是一段后缀,并且一定有一个位置同时满足这两个条件,因为删除相邻两个数的子序列中,奇数位和和偶数位和至多一个会发生改变。于是 Bob 选择删去这个位置,接下来要说明对于所有奇数位和 \(<l\) 且偶数位和 \(>r\) 的序列 \(a\),一定是 Bob 获胜。
对于这样的一个序列 \(a\),Alice 选择一个长度为 \(n-2\) 的子序列,相当于删掉两个数,那么无论删掉哪两个数,剩下的子序列依然会满足奇数位和 \(<l\)、偶数位和 \(>r\) 中的至少一个(分删的数是否同奇偶来考虑)。也就是说 Alice 在选择第一个数后,不能找到长为 \(n-2\) 的子序列满足奇数位和 \(\ge l\) 且偶数位和 \(\le r\),根据上面的结论,Bob 总能找到下一步要删的数使得剩下的子序列还满足奇数位和 \(<l\) 且偶数位和 \(>r\),这样就递归到了 \(n-2\) 的子问题。当 \(n=2\) 时,显然 Bob 必胜,于是就可以通过归纳法说明了这种情况下 Bob 必胜。
枚举 Alice 第一次选哪个数和剩下的数中每个长为 \(n-2\) 的子序列,计算奇数位和和偶数位和判断即可,复杂度 \(\mathcal{O}(n^2)\)。
Submission #70152163 - AtCoder Grand Contest 056
[AGC056E] Cheese
有一个长度为 \(n\) 的圆,将某个点设为坐标 \(0\),顺时针走 \(x\) 的位置为坐标 \(x\),对于每个 \(0\le i < n\),在 \(i+0.5\) 处有一只老鼠。定义一次操作为:
- 随机选择一个 \(0\le i < n\),选到 \(i\) 的概率为 \(a_i\%\)。
- 从坐标 \(i\) 处扔下一块奶酪,奶酪会沿着顺时针方向前进,每当奶酪经过一只老鼠时,如果这只老鼠吃过奶酪则忽略,否则奶酪会有 \(\frac 1 2\) 的概率被吃掉。奶酪会一直移动直到被吃掉。
经过 \(n-1\) 次操作后恰好有一只老鼠没吃过奶酪。对于每个 \(0\le i < n\),求出位于 \(i+0.5\) 处的老鼠最后没有吃到奶酪的概率。
答案对 \(998244353\) 取模。\(n\le 40\)。
首先你需要注意到我们只关心奶酪在哪些点释放的可重集,而与释放顺序无关。考虑证明,相当于要证明任意两次操作都可以交换。考虑每次释放一个奶酪会有一个判定过程,设 \((x,y)\) 表示判断奶酪 \(x\) 从 \(y\) 面前经过时有没有被吃,那么设奶酪 \(a\) 在 \(p_a\) 释放,\(b\) 在 \(p_b\) 释放。那么这两次操作就会有个判断序列:\((a,p_a),(a,p_a+1),\ldots,(b,p_b),(b,p_b+1),\ldots\)。
也就是说我们可以交换任意两次 \((a,x),(b,y)\) 的判断,如果 \(x\ne y\),显然这两次判断没有关系,可以交换。否则,如果 \(x=y\),如果这两次操作都没有被 \(x\) 吃掉,那么交换了也没影响。否则就是 \(a\) 被 \(x\) 吃掉,然后 \(b\) 判断到 \(x\) 已经吃过了就会继续走下去,如果我们交换这两次操作,可以看成 \(b\) 被 \(x\) 吃掉,然后 \(a\) 继续走下去。因为两块奶酪本质没有区别,所以这样交换不会对答案有影响。
接下来的过程应该是容易的。我们对每个 \(x\) 分别计算答案,不妨设计算 \(0\) 的答案。我们枚举每个可重集,计算答案后再乘上这个可重集的出现概率再贡献给最终答案。因为不考虑顺序,所以可以将所有奶酪都走一圈到坐标 \(0\) 处, 当有 \(k\) 个奶酪经过一只老鼠时,这只老鼠吃掉某个奶酪的概率为 \(1-\frac{1}{2^k}\)。于是考虑 dp,我们从 \(1\) 开始,设 \(f_{i,j,k}\) 表示到了坐标 \(i\),\(1\sim i\) 中共有 \(j\) 块奶酪,现在还剩下 \(k\) 块的概率,转移为:
接下来考虑在坐标 \(0\) 处有 \(k\) 块奶酪,有 \(k+1\) 只老鼠,求 \(0.5\) 的老鼠最后没有吃掉奶酪的概率。这个时候我们在一个一个奶酪的释放,考虑第一个奶酪,它在第一圈被某个不在 \(0.5\) 的老鼠吃掉的概率为 \(\frac{1}{2^2}+\ldots+\frac{1}{2^{k+1}} = \frac 1 2-\frac{1}{2^{k+1}}\),记为 \(p\)。在第一圈没被吃掉的概率为 \(\frac{1}{2^{k+1}}\),接下来我们枚举这块奶酪是在第几圈被吃掉的,则概率为:
然后第 \(2\) 块奶酪就是 \(k\) 只老鼠的子问题,第 \(3\) 块就是 \(k-1\),一直到两只老鼠,所以总的概率为 \(\frac{2^k-1}{2^{k+1}-1}\times \frac{2^{k-1}-1}{2^k-1}\times \ldots\times \frac{2^1-1}{2^2-1} = \frac{1}{2^{k+1}-1}\)。所以最后答案为:
单次计算复杂度为 \(\mathcal{O}(n^4)\),总复杂度为 \(\mathcal{O}(n^5)\)。
AGC055
[AGC055A] ABC Identity
skip。Submission #70323182 - AtCoder Grand Contest 055
[AGC055B] ABC Supremacy
给定一个由 ABC 构成的长为 \(n\) 的字符串 \(s\) 和 \(t\),定义一次操作为:将 \(s\) 中的某个字串 ABC 或 BCA 或 CAB,替换为 ABC、BCA、CAB 中的任意一个,求 \(s\) 能否变成 \(t\)。
\(n\le 5\times 10^5\)
可以考虑一个经典 trick:奇数位翻转。但这个题是 ABC,于是我们考虑将第 \(i\) 个字符减去 \(i\),然后模 \(3\),对 \(s,t\) 都这么操作。那么一个原来的子串 ABC、BCA、CAB,操作后就是 AAA、BBB、CCC。于是现在问题就变成了,每次可以选择三个连续相同的字符,变成另外一个字符,求 \(s\) 能否能变成 \(t\)。
注意到 AAAX 可以变化为 XXXX,再变为 XAAA,相当于一个 AAA 可以和任何一个字符交换,于是可以直接把这个 AAA 移到序列末尾,也就相当于将 AAA 从序列中删掉。那么将 \(s\) 和 \(t\) 都不断删去三个连续相同的字符,判断剩下的序列是否一致即可。
Submission #70323276 - AtCoder Grand Contest 055
[AGC055C] Weird LIS
给定 \(n,m\),求满足以下条件的正整数序列 \((a_1,\ldots,a_n)\) 的个数:
- \(\forall 1\le i\le n\),有 \(2\le a_i\le m\)。
- 存在一个 \(1\sim n\) 的排列 \(p\),满足 \(\forall 1\le i\le n\),\(a_i\) 等于 \(p\) 去掉 \(p_i\) 后的序列的最长上升子序列长度。
答案对某个给定的质数 \(q\) 取模。\(m < n\le 5000\)
考虑给定某个序列 \(a\),如何判断是否有满足条件的原序列 \(p\)。设 \(p\) 的 LIS 长度为 \(x\),那么 \(a_i\) 只会出现 \(x\) 和 \(x-1\),并且 \(a_i=x-1\) 当且仅当 \(a_i\) 出现在了所有 LIS 中,那么肯定有 \(x-1\) 的出现次数不超过 \(x\)。设 \(x-1\) 出现了 \(c\) 次,那么我们还需要找到 \(x-c\) 个位置能插到这 \(c\) 个位置中作为一个 LIS,称为关键位,并且在删掉关键位中的某个后 LIS 长度不变,所以每个位置一定都能找到一个可以替换这个位置并且 LIS 不变的位置,称为候选位。
手玩一下可以发现,两个位置的候选位一定不同,于是设任意两个 \(x-1\) 之间有 \(p\) 个位置,那么最多能有 \(\lfloor\frac p 2\rfloor\) 个位置作为关键位。如果所有段的 \(\lfloor\frac p 2\rfloor\) 之和 \(\ge x-c\) 那么就一定能构造出一组解,否则一定无解,于是这就是充要条件。接下来考虑计数,我们枚举 \(x\) 和 \(c\),发现 \(x=v,c=n\) 和 \(x=v-1,c=0\) 不可能同时有解,所以不会算重。那么现在要计算有多少种从 \(n\) 个位置选 \(c\) 个位置的方案,使得 \(\lfloor\frac p 2\rfloor\) 之和 \(\ge x-c\)。
于是考虑计算从 \(n\) 个位置选 \(c\) 个位置,使得 \(\lfloor\frac p 2\rfloor\) 之和恰好等于 \(v\) 的方案数,然后做一遍后缀和。发现如果知道了 \(c,v\),那么就知道了恰好有 \(n-c-2v\) 个 \(p\) 为奇数。于是方案数就是先从 \(c+1\) 段中选出 \(n-c-2v\) 段为奇数,然后再将 \(v\) 个关键位置放入 \(c+1\) 个段中,即 \({c+1\choose n-c-2v}{v+c\choose c}\)。总复杂度 \(\mathcal{O}(n^2)\)。
Submission #70323701 - AtCoder Grand Contest 055
[AGC055D] ABC Ultimatum
一个长度为 \(3n\) 的只含 ABC 的字符串 \(s\) 是好的,当且仅当存在一种将 \(s\) 划分为 \(n\) 个长度为 \(3\) 的子序列的方法,使得每个子序列都是 ABC、BCA、CAB 中的一个。给定一个长为 \(3n\),由 ABC? 构成的字符串 \(s\),求有多少种将每个 ? 替换为 ABC 中的一个的方案,使得最终得到的 \(s\) 是好的。
答案对 \(998244353\) 取模。
人类智慧。
考虑找到一个判断 \(s\) 是否是好的的充要条件。我们发现,ABC 在 ABC、BCA、CAB 中是唯一一个满足 C 在 A 后面的字符串,那么对于任意一个前缀 \(s_{1\ldots i}\),计算 \(cnt_A-cnt_C\),那么至少有这么多个 A 必须和 \(i\) 后面的 C 匹配,也就是说 ABC 至少会出现这么多次。记 \(A',B',C'\) 分别表示所有前缀中 \(cnt_A-cnt_C,cnt_B-cnt_A,cnt_C-cnt_B\) 的最大值,也就是 ABC、BCA、CAB 出现次数的下界,显然需要有 \(A'+B'+C'\le n\),并且这个条件也是充分的。
考虑证明充分性,我们将 \(s\) 复制一份拼在后面,那么 \(A',B',C'\) 不会改变,有以下构造方式:第 \(i\) 个 A 和第 \(i+B'\) 个 B 和第 \(i+B'+C'\) 个 C 进行匹配,如果下标 \(>n\) 就 \(-n\)。因为 \(cnt_B-cnt_A\) 最大为 \(B'\),所以第 \(i+B'\) 个 B 一定在第 \(i\) 个 A 后面,否则我们取第 \(i+B'\) 个 B 所在的位置,这个前缀中 \(cnt_B-cnt_A\) 一定 \(>B'\),与条件不符。同理,第 \(i+B'+C'\) 个 C 一定在第 \(i+B'\) 个 B 后面,第 \(i+B'+C'+A'\) 个 A 一定在第 \(i+B'+C'\) 个 C 后面。
而因为 \(A'+B'+C'\le n\),那么在这组 ABC 中,C 没有超过下一个 A 所在位置,也就是说将下标 \(-n\) 后一定是 ABC、BCA、CAB 中的一个,于是我们就证明了这个条件的充分性。
接下来 dp 是简单的。设 \(f_{i,j,k,x,y,z}\),表示前 \(i+j+k\) 位中,用了 \(i\) 个 A,\(j\) 个 B,\(k\) 个 C,有 \(A'=x,B'=y,C'=z\),然后 \(\mathcal{O}(1)\) 转移。总复杂度为 \(\mathcal{O}(n^6)\)。
Submission #70324692 - AtCoder Grand Contest 055
然后这个题目还有个加强版:P12472 [集训队互测 2024] 基础 ABC 练习题
加强版还增加了两个字符串是好的的条件:给定集合 \(S_1,S_2\),要求划分出的 \(n\) 个子序列中,ABC 的出现次数 \(\in S_1\),BCA 的出现次数 \(\in S_2\)。并且 \(n\le 60\)。
先考虑将原问题的时间复杂度优化到 \(\mathcal{O}(n^5)\),设 \(f(x,y,z)\) 表示 \(s\) 中 \(A'\le x,B'\le y,C'\le z\) 的答案,那么只需枚举最终 \(A',B'\) 是多少,那么有 \(C'\le n-A'-B'\),用容斥即可算出 \(A'\) 恰好为 \(x\),\(B'\) 恰好为 \(y\),\(C'\le z\) 的答案,即:
接下来考虑加上限制条件,现在已经枚举了 \(A',B'\) 是多少,那么划分出来的 ABC、BCA 的个数就至少为 \(A',B'\),找到 \(S_1,S_2\) 中 \(\ge A',\ge B'\) 的最小的数 \(x,y\),那么要有 \(C'\le n-x-y\)。而如果我们找到了一组 \(A',B',C'\) 的解,那么将第 \(i\) 个 A 和第 \(i+y\) 个 B 和第 \(i+y+(n-x-y)\) 个 C 匹配,那么一定恰好有 \(x\) 个 ABC,\(y\) 个 BCA。那么我们只需要将上式的 \(n-i-j\) 改为 \(n-x-y\) 即可。复杂度还是 \(\mathcal{O}(n^5)\)。
[AGC055E] Set Merging
有 \(n\) 个集合,初始时 \(S_i = \{i\}\),定义一次操作为:
- 选择一个 \(1\le i < n\),将 \(S_i\) 和 \(S_{i+1}\) 同时替换为 \(S_i\cup S_{i+1}\)。
给定 \(n\) 个区间 \([l_i,r_i]\),表示最终 \(S_i = [l_i,r_i]\cap Z\),求最少用多少次操作可以达到最终状态,或者报告无解。
\(n\le 5\times 10^5\)
人类智慧的加强版,可以称为外星人智慧。
我们有如下转化:设 \(p\) 为 \(1\sim n\) 的排列,初始时 \(p_i=i\),一次对 \(i\) 的操作为交换 \(p_i,p_{i+1}\),最终有 \(S_i = [\min\{p_i,\ldots,p_n\},\max\{p_1,\ldots,p_i\}]\)。
考虑证明,用归纳法去说明,初始时每个 \(S_i\) 都满足条件。对于一次操作,如果 \(p_i > p_{i+1}\),那么 \(S_i = S_{i+1}\),因为我们要操作数最小,所以不会出现这样的操作。否则,\(p_i < p_{i+1}\),我们想让 \(l_i,l_{i+1}\) 同时变为 \(\min(l_i,l_{i+1})\),即 \(\min\{p_i,\ldots,p_n\}\)。交换变为了 \(p_{i+1},p_i\),那么 \(\min\{p_{i+1},p_i,p_{i+2},\ldots,n\}\) 一定等于 \(\min\{p_i,p_{i+2},\ldots,n\}\),因为 \(p_{i+1} > p_i\),所以最小值一定在后面,也就达到了 \(l_i,l_i+1\) 同时变为 \(\min(l_i,l_{i+1})\) 的目的。\(r_i,r_{i+1}\) 同理。
现在问题就变成了求一个排列 \(p\),满足 \(\min(p_i,\ldots,p_{n}) = l_i,\max(p_1,\ldots,p_i) = r_i\),并且因为每次操作是交换相邻两个数,所以操作数就是 \(p\) 的逆序对数。现在我们知道了所有后缀 \(\min\) 和前缀 \(\max\),首先肯定要有 \(l_i\le l_{i+1},r_i\le r_{i+1}\),如果 \(l_i < l_{i+1}\),那么有 \(p_i = l_i\),如果 \(r_i\ne r_{i+1}\),有 \(p_{i+1} = r_{i+1}\)。并且 \(p_1 = r_1,p_n = l_n\),所有已知的条件肯定不能矛盾,即不能出现一个位置要填两个不同的数,或一个数要填到两个不同的位置。
接下来我们要填剩下的位置,只需满足 \(p_i\in [l_i,r_i]\) 即可。可以发现将剩下未确定的数从小到大填进去一定是最优的,因为如果不是从小到大填进去并且也符合条件,那么交换某个逆序对一定还是满足条件。并且,这样子填数还可以让逆序对数最小,所以我们将剩下的数填了后判一下是否合法,然后求逆序对即可。复杂度 \(\mathcal{O}(n\log n)\)。
Submission #70334494 - AtCoder Grand Contest 055
[AGC055F] Creative Splitting
定义一个正整数序列 \((a_1,\ldots,a_k)\) 是好的,当且仅当 \(\forall 1\le i\le k\),满足 \(a_i\le i\)。定义一个序列 \((b_1,\ldots,b_{nk})\) 是合法的,当且仅当存在一种将 \(b\) 划分为 \(n\) 个好的子序列的方式。给定 \(n,k\),你需要对所有 \(1\le pos\le nk,1\le val\le k\),求出有多少个合法的序列满足 \(b_{pos} = val\)。
答案对给定的质数 \(p\) 取模。\(n,k\le 20\)
神仙题。
考虑如何判断一个 \(b\) 是否合法,可以考虑贪心,但如果从前往后贪心,有可能某个序列突然加着加着就不能加了,所以我们考虑倒着做。相当于有 \(n\) 个初始值为 \(k\) 的变量,每次找到最小的 \(\ge b_i\) 的变量,将其 \(-1\),无解相当于找不到 \(\ge b_i\) 的变量。
我们把上述过程刻画到二维平面上。初始时有一个 \(n\times k\) 的矩阵,每次要将球塞到某个格子,即找到最下面的第 \(b_i\) 列没有球的位置,然后将球放在这一行的最右边,并按每行的球数进行排序。相当于让球从第 \(b_i\) 列最上方落下来,然后再往右靠。那么这是一个杨表的结构,于是我们将杨表转置,即不维护每行的球数而是维护每列的球数。那么就是有 \(k\) 个初始为 \(0\) 的变量 \(p_i\),每次将 \(p_{b_i}\) 加一,然后对 \(p\) 进行排序,每次要求 \(p_{b_i} < n\)。
可以发现转化后的问题有很大的优势,因为如果没有 \(b_{pos} = val\) 的限制,那么每次 \(b_i\) 可以取到 \([1,k]\) 中的任意一个,那么每次根本就不用排序。因为排序后本质上是将每列换了个位置,但如果 \(b_i\in [1,k]\) 相当于每列都可能会落一个球,那是否交换位置是没有影响的。于是如果没有 \(b_{pos} = val\) 的限制,那么答案就是 \(1\sim k\) 每个数有 \(n\) 个的可重集计数,即 \(\frac{(nk)!}{(n!)^k}\)。
接下来考虑 \(b_{pos} = val\) 的限制,那么在 \(\sum p_i = nk-pos\) 时就必须要排一次序,然后要求 \(p_{val} < n\) 并将 \(p_{val}\) 加 \(1\),然后再填完剩下的。于是我们枚举 \(p\) 序列排序后是长什么样的并求出贡献,贡献分三部分,第一部分考虑 \(p\) 是排序后的,那么排序前的方案数就是对 \(p\) 进行可重集计数;第二部分是前面用 \(nk-pos\) 步填满了当前的 \(p\),方案数和没有限制时相同;第三部分是后面用 \(pos-1\) 步填完剩下的部分,计算同理,注意 \(b_{val}\) 会先加个 \(1\)。那么答案就是:
于是直接 dp 即可,设 \(f_{i,j,k}\) 表示考虑了 \(p\) 中所有 \(\le i\) 的数,填了 \(p\) 的前 \(j\) 个数,\(p\) 中数的和为 \(k\)。转移时枚举当前 \(i\) 填了多少个即可。同一个 \(val\) 的答案可以一起求,复杂度为 \(\mathcal{O}(n^2k^4)\)。
Submission #70330053 - AtCoder Grand Contest 055
AGC054
[AGC054A] Remove Substrings
skip。Submission #70341013 - AtCoder Grand Contest 054
[AGC054B] Greedy Division
注意到钦定了两个人选什么数和分别选的顺序后贡献为 \(1\),于是 dp 即可。Submission #70341444 - AtCoder Grand Contest 054
[AGC054C] Roughly Sorted
skip。Submission #70342063 - AtCoder Grand Contest 054
[AGC054D] (ox)
给出一个由 \(()ox\) 构成的字符串 \(s\),每次可以交换 \(s\) 相邻两个字符,求最少用多少次操作,可以使得 \(s\) 满足:
- 将 \(o\) 替换为 \(()\),将 \(x\) 替换为 \()(\) 后,得到的字符串是一个合法的括号序列。
\(|S|\le 8000\)
首先考虑如果只有 \(()\) 应该怎么做,将 \((\) 看成 \(1\),\()\) 看成 \(-1\),我们从前往后枚举,如果某个前缀和为负数,那么就将后面第一个 \((\) 交换过来,这样显然最优。证明可以考虑如果 \(1\sim i\) 的和为负数 \(-s\),那么至少有这么 \(s\) 个 \((\) 会从右边交换过来,于是答案的下界为所有 \(<0\) 的前缀和的绝对值之和,而上述构造可以取到下界。
接下来考虑有 \(ox\),在原本合法的序列加入 \(o\) 不会影响,\(x\) 则要求至少要在一对 \(()\) 里,即此处的前缀和 \(>0\)。我们发现,如果不交换 \(ox\) 那么答案和原来相同。因为如果发生了 \(ox\) 的交换,一定是要把这个 \(x\) 换到某对 \(()\) 里面,假设是向右换到了一对 \(()\) 里,那么将这个 \((\) 交换到 \(x\) 左边一定不劣,向左交换同理。
接下来我们考虑最终得到的字符串 \(s'\),那么操作数就是将 \(s'\) 中每个字符映射到原来 \(s\) 中的每个字符,假设 \(s'_i\) 映射到了 \(s_{p_i}\),\(p\) 的逆序对就是答案。我们将 \(()\) 和 \(ox\) 分开考虑,求出 \(s'\) 中 \(()\) 和 \(ox\) 的子序列分别长什么样,首先 \(ox\) 的子序列一定和原来一样,因为 \(ox\) 不会发生交换。而 \(s'\) 中 \(()\) 的子序列一定是原来 \(s\) 中 \(()\) 的子序列做只有 \(()\) 的贪心后形成的串,于是我们就可以确定这两个子序列每个字符的 \(p_i\) 是什么。
接下来相当于要将两个子序列归并起来,要让逆序对最少,设 \(f_{i,j}\) 表示归并了 \(()\) 的前 \(i\) 个和 \(ox\) 的前 \(j\) 个的最小逆序对数,需要注意在放 \(x\) 时要保证做完贪心后的 \(()\) 子序列的前 \(i\) 位和 \(>0\)。转移是简单的,复杂度为 \(\mathcal{O}(|S|^2)\)。
Submission #70348939 - AtCoder Grand Contest 054
[AGC054E] ZigZag Break
给定 \(n,a\),求有多少个 \(1\sim n\) 的排列 \(p\) 满足:
- \(p_1 = a\)
- 可以通过重复以下操作,使得 \(p\) 中剩 \(2\) 个数:
- 选择 \(p\) 中三个连续的数 \(x,y,z\),满足 \(y < \min(x,z)\) 或 \(y > \max(x,z)\),将 \(y\) 从序列 \(p\) 中删去。
\(T\) 组询问。\(T\le 5\times 10^5,a\le n\le 10^6\)
不妨设 \(p_1 < p_n\),显然最后剩的数为 \(p_1,p_n\),考虑求出一个 \(p\) 能删到只剩 \(p_1,p_n\) 的充要条件。
如果存在一个 \(1\le i < n\) 满足 \(p_i\le p_1,p_{i+1}>p_n\),那么 \(p\) 就一定能删完,因为对于第 \(1\sim i\) 个数能删就删一定会得到一个递减的序列,第 \(i+1\sim n\) 个数能删就删也会得到一个递减的序列,接下来每个数能删就删一定可以删完。
并且也是一个必要条件,可以使用归纳法证明。假设原本 \(p\) 中不存在符合条件的 \(i\),删掉某个数后出现了符合条件的 \(i\),相当于删掉了一个 \(\le p_1\) 的数和一个 \(\ge p_n\) 的数中间隔的一个数,如果这个数 \(\le p_1\) 或 \(\ge p_n\),那么原来就有符合条件的 \(i\),否则这个数 \(\in (p_1,p_n)\) 根据题目这个数不能删。于是假设不成立,我们删掉任意一个数后递归到 \(n-1\) 的子问题,一直到 \(n=3\) 一定无解。
接下来考虑计数,我们用总方案减去不合法的方案,因为钦定了 \(p_1 < p_n\),所以如果 \(p_1 > p_n\),我们可以让所有 \(p_i\) 变为 \(n-p_i+1\) 来一一对应每一种 \(p_1 = n-a+1\) 且 \(p_1 < p_n\) 的方案。设 \(calc(x)\) 表示求有多少个 \(p_1=x,p_1<p_n\) 的序列不合法,那么答案为 \((n-1)!-calc(x)-calc(n-x+1)\)。
考虑计算 \(calc(x)\),我们枚举 \(p_n-p_1-1\) 是多少,假设为 \(k\),考虑一个一个数插入到 \(p\) 中,要求每个 \([1,p_1]\) 间的数后面不能是 \([p_n,n]\) 间的数。首先 \((p_1,p_n)\) 间的 \(k\) 个数可以任意排,即 \(k!\),然后放 \([1,p_1]\) 间的数,注意到 \(p_n\) 会放在序列末尾,于是第一个数只有 \(k\) 个位置可以插,后面的数同理。\(p_1\) 会插在开头,其余 \(p_1-1\) 个数方案数为 \(k^{\overline{p_1-1}}\)。\([p_n,n]\) 间的数同理,方案数为 \(k^{n-p_n}\),带入 \(p_n=p_1+k+1\),于是总的答案为:
于是可以 \(\mathcal{O}(1)\) 回答每组询问。
Submission #70343287 - AtCoder Grand Contest 054
[AGC054F] Decrement
给定 \(n\) 和两个正整数序列 \((A_1,\ldots,A_n)\) 和 \((B_1,\ldots,B_{n-1})\),你可以进行若干次以下操作:
- 选择 \(i,j\) 满足 \(1\le i < j\le n\),将 \(A_i,A_j,B_i,\ldots,B_{j-1}\) 都减一,保证操作后不出现负数。
设 \(m\) 为最大的操作次数,求在 \(m\) 次操作后有多少种本质不同的序列 \(A\)。
答案对 \(998244353\) 取模。\(n\le 2\times 10^5,A_i,B_i\le 10^9\)
考虑判断怎样一个最终的 \(A,B\) 序列是可以得到的,设 \(a_i,b_i\) 表示 \(A_i,B_i\) 减少了多少,现在要判断一组 \(a,b\) 是否合法。对于每个 \(1\le i\le n\),观察 \(a_i,b_{i-1},b_i\)(设 \(b_0=b_n=0\)),可以发现每次操作一定是这 \(3\) 个数都不变,或者其中恰好两个 \(+1\),可以分 \(i\) 和 \(l,r\) 的关系来讨论。
于是就有两个显然的必要条件,\(\forall 1\le i\le n\),要满足 \(a_i+b_{i-1}+b_i\) 为偶数,并且 \(\max\{a_i,b_{i-1},b_i\}\le \frac{a_i+b_{i-1}+b_i} 2\)。而这也是充分条件,因为对于每次操作,设满足 \(a_i = b_{i-1}+b_i\) 的 \(i\) 为关键点,选择两个相邻的关键点操作即可(即中间没有其他关键点),显然 \(1,n\) 都是关键点,所以一定能找到这样的点对。并且这样操作后依然满足两个条件。
可以发现对于每个 \(i\),\(B_i\) 最多取 \(B_{i-1}+A_i\),可以将 \(B_i\) 与这个值取 \(\min\),同理也可以将 \(B_{i-1}\) 与 \(B_i+A_i\) 取 \(\min\),正着倒着各扫一遍,每个 \(i\) 就都满足了 \(|B_i-B_{i-1}|\le A_i\)。
接下来注意到,如果某个 \(i\) 满足 \(A_i\ge B_{i-1}+B_i\),那么 \([1,i]\) 和 \([i,n]\) 是独立的。因为可以令 \(A_i = B_{i-1}\) 求出 \([1,i]\) 的答案,再令 \(A_i = B_i\) 求出 \([i,n]\) 的答案,然后将 \(a_i\) 设为 \(b_{i-1}+b_i\) 即可,这个值一定 \(\le A_i\)。所以我们可以将原序列划分为若干个区间来考虑,现在考虑求一个区间 \([l,r]\) 的答案,满足 \(A_l=B_l,A_r=B_{r-1}\),并且 \(\forall l<i<r\),有 \(|B_{i-1}-B_i|\le A_i < B_{i-1}+B_i\)。
先考虑求出操作次数的最大值,即 \(\sum a_i\) 的最大值,显然 \(\sum a_i\) 需要为偶数。如果 \(\sum A_i\) 为偶数,那么答案的上界肯定是这个,并且这个上界一定可以取到。设 \(a_l = b_l = A_l\),对于 \(l < i\le r\) 的 \(i\),根据 \(a_i+b_{i-1}\) 的奇偶性将 \(b_i\) 设为 \(B_i\) 或 \(B_i-1\),这样子一定合法,证明可以分几种情况考虑一下。而如果 \(\sum A_i\) 为奇数,可以发现当 \(a\) 为 \((A_l,A_{l+1},\ldots,A_{r-1},A_r-1)\) 时也一定合法,此时答案为 \(\sum A_i-1\)。
接下来考虑有多少种剩余的 \(A\),即有多少种不同的 \(a\) 序列。如果 \(\sum A_i\) 为偶数,显然只有一种,否则就是看哪些 \(A_i\) 减一之后构成的 \(a\) 满足条件。我们可以正着扫一遍,算出当所有 \(a_i=A_i\) 时,每个 \(b_i\) 能取到哪些值,这些值一定是一个区间内的所有奇数/偶数,同理再倒着扫一遍。
每次判断能否让某个 \(A_i\) 减一时,就用 \(A_i-1\) 和正着扫的 \(b_{i-1}\) 算出 \(b_i\) 的取值范围,看是否和倒着扫的 \(b_i\) 的取值范围有交,如果有交说明可以让 \(A_i\) 减一。统计出有多少个这样的 \(A_i\),假设有 \(cnt\) 个,那么答案就是所有段 \(cnt\) 的乘积。复杂度为 \(\mathcal{O}(n)\)。
Submission #70666151 - AtCoder Grand Contest 054
AGC053
[AGC053A] >< again
skip。Submission #70875753 - AtCoder Grand Contest 053
[AGC053B] Taking the middle
skip。Submission #70875819 - AtCoder Grand Contest 053
[AGC053C] Random Card Game
有 \(2n\) 张卡牌,编号为 \(1\sim 2n\),初始时随机将这 \(2n\) 张牌分为两堆,每堆 \(n\) 张并且内部顺序随机。一个玩家初始时知道所有卡牌的顺序,他每次可以进行以下操作:
- 选择一个 \(k\),要求 \(k\) 不大于任意一堆的牌数,将两堆牌从上往下数第 \(k\) 张牌中小的移除。
定义他的得分为最小的操作次数使得其中一堆卡牌为空,求玩家的期望得分。
答案对 \(10^9+7\) 取模。\(n\le 10^6\)。
先考虑给定两堆牌,得分是什么。可以发现一定是将不含 \(2n\) 的那一堆牌删空,不妨设为左堆,并且这一定是可以做到的,考虑最小操作次数。首先我们一定要删完左堆,于是问题变成了最少需要删右堆中的多少个数。
设左堆从上到下为序列 \(a\),右堆为序列 \(b\),那么每个 \(a_i\) 需要找到一个 \(b_j>a_i\) 并在对齐时删掉 \(b_j\)。于是我们找到 \(p_i\) 表示最小的 \(j\) 满足 \(b_j > a_i\),那么答案有个下界为 \(\max\{p_i-i\}\),因为对每个 \(i\) 至少需要删掉右堆中的 \(p_i-i\) 个数才能使 \(a_i\) 与 \(b_j\) 对齐。并且这个下界也是可以达到的,设下界为 \(s\),我们可以每次删掉最小的满足 \(p_i>i\) 的 \(b_i\),重复 \(s\) 次,就有每个 \(p_i\le i\),接下来每次再删去最大的满足 \(p_i=i\) 的 \(a_i\) 即可。
也就是说我们要求 \(\max\{p_i-i\}\) 的期望,求出 \(\max\{p_i-i\}\) 为每个值得概率即可。然后差分为对每个 \(v\in [0,n-1]\) 求出 \(\max\{p_i-i\}\le v\) 的概率,也就是说每个 \(p_i-i\) 都要 \(\le v\),即对于每个 \(i\),\(b_1,b_{1,\ldots,\min(n,i+v)}\) 中至少存在一个 \(>a_i\) 的数。我们可以考虑按 \(b_1,\ldots,b_{v+1},a_1,b_{v+2},a_2,b_{v+3},\ldots\) 的顺序依次确定每个位置在前面数中的相对大小。
对于 \(b_1,\ldots,b_{v+1}\) 没有限制,而 \(a_1\) 要求 \(a_1\) 不能是 \(b_1,\ldots,b_{v+1},a_1\) 中的最大值,也就是有 \(1-\frac{1}{v+2}\) 的概率。插入 \(b_{v+2}\) 没有限制,而对于 \(a_2\) 有 \(1-\frac{1}{v+4}\) 的概率,后面依次类推。所以答案为 \(\prod\limits_{i=1}^n (1-\frac{1}{i+\min(n,i+v)})\),于是我们可以 \(\mathcal{O}(n^2)\) 计算答案。
可以发现上式容易优化,将式子展开就是 \(\frac{v+1}{v+2}\times \frac{v+3}{v+4}\times\ldots\times \frac{2n-i-1}{2n-i}\times\ldots\times \frac{2n-1}{2n}\),于是只需维护 \(f_i = i\times(i-2)\times(i-4)\times \ldots\) 和 \(f_i\) 的逆元即可。注意最后要将答案 \(+n\) 然后乘 \(2\),因为我们钦定了 \(a\) 序列不含 \(2n\)。复杂度为 \(\mathcal{O}(n)\)。
Submission #70876278 - AtCoder Grand Contest 053
[AGC053D] Everyone is a winner
有 \(n\) 个参赛者参加有 \(n\) 个题目的竞赛,每个参赛者解决每个题目会花费 \(1\sim 3\) 分钟时间。具体地,第 \(i\) 个参赛者分别会在 \(a_i,b_i,c_i\) 道题目花费 \(1,2,3\) 分钟,保证 \(a_i+b_i+c_i=n\)。你需要安排每个参赛者的解题顺序,使得 \(\forall 1\le i\le n\),第 \(i\) 个人在所有人中最先解决前 \(i\) 道题(可以并列),判断是否有解。
\(n\le 2\times 10^5\)
我们首先可以求出当所有人按时间花费从多到少做所有题时,最快做出前 \(i\) 道题的人的用时 \(t_i\),显然一个必要条件是对于所有 \(i\),第 \(i\) 个人以最快速度做出前 \(i\) 道题的用时需要 \(\le t_i\),但这个条件并不是充要的。我们可以考虑倒着做,给每个人安排做题顺序。
对于当前考虑的人,我们首先要保证他是做完前 \(i\) 个题中最快的,然后要安排前面的做题顺序使得他做得尽量慢,这样才能尽可能满足前面的人的限制。例如第 \(n\) 个人,所有人完成 \(n\) 道题的时间是固定的,所以可以直接看出第 \(n\) 个人是否是所有人中最快的,然后第 \(n\) 个人一定是按时间花费从多到少的做,这样可以保证前面做的尽量慢。
具体地,对于第 \(i\) 个人,我们先要安排做题顺序使得完成前 \(i\) 道题的时间 \(\le t_i\),如果无法做到就无解。然后要在这个基础上使得他做前面的题尽量慢,也就是说我们要让完成前 \(i\) 道题的时间尽量长,并且做前 \(i\) 道题的顺序一定是按时间花费从多到少地做。
而如果有多种方案能使得完成前 \(i\) 题的时间达到最长,那一个方案一定能通过另一个方案多次执行将 \(2,2\) 替换为 \(1,3\) 得到,可以发现 \(3,1\) 比 \(2,2\) 优,所以如果有多种方案,我们应该选择 \(1\) 最多的。而后 \(n-i\) 题依然是按时间花费从多到少地做。求出第 \(i\) 个人的做题顺序后,更新所有 \(j < i\) 的 \(t_j\),然后一直做下去即可。
为什么这样子是对的?可以发现我们并没有对于 \(i<j\) 检验第 \(i\) 个人完成前 \(j\) 题的时间是否不比第 \(j\) 个人快,但我们可以证明在本题的限制条件下一定满足第 \(i\) 个人不比第 \(j\) 个人快。
对于第 \(i\) 个人,可能造成影响的是他在做前 \(i\) 题时没有将耗时 \(3\) 的题目用完,或用完了耗时 \(3\) 的题目但没用完耗时 \(2\) 的题目,假设取到 \(t_i\) 的是第 \(j\) 个人(即第 \(j\) 个人在按时间从多到少做题时最快做完前 \(i\) 个题),那么第 \(j\) 个人按时间从多到少做题时第 \(i\) 题的花费至少 \(\le 2\),也就是说对于所有 \(j>i\) 都满足 \(t_j\le t_i+2(j-i)\)。
而对于第 \(i\) 个人,他会在做完前 \(i\) 道题后再按 \(3,2,1\) 的时间花费做题,因为 \(t_j\le t_i+2(j-i)\) 所以他做 \(3,2\) 的题目时依然满足 \(t_j\) 的限制,而当他开始做 \(1\) 的题目时又相当于是以最慢的速度在做,不会有影响。
具体实现时,可以把时间都转化为 \(0,1,2\)。对于求一个耗时最长且 \(0\) 最多的方案,可以考虑先选出一个耗时最短的方案,然后再用调整法调整为耗时最长,再调整为 \(0\) 最多。\(t_i\) 的更新暴力是 \(\mathcal{O}(n^2)\) 的,但可以发现 \(t_i\) 一定是形如一个三段的凸包,维护每一段即可。时间复杂度 \(\mathcal{O}(n)\)。
Submission #70879595 - AtCoder Grand Contest 053
[AGC053E] More Peaks More Fun
给定 \(n\) 个二元组 \((a_i,b_i)\),保证所有 \(a_i,b_i\) 构成了 \(1\sim 2n\) 的排列。求在 \(n!\) 种二元组的排列中,有多少排列满足以下条件:
- 存在一种任意交换一些二元组的内部顺序的方案,依次将 \(a_1,b_1,\ldots,a_n,b_n\) 写下来构成序列 \(c\),满足序列 \(c\) 的峰值个数恰好为 \(n-1\),其中峰值为满足 \(1<i<n\land c_{i-1}<c_i\land c_{i+1}<c_i\) 的 \(i\)。
答案对 \(10^9+7\) 取模。
比较简单的金牌题?
不妨设每个二元组满足 \(a_i<b_i\)。先考虑给定一个二元组的排列,求是否能满足条件。可以发现限制条件非常严格,因为峰值最多只能有 \(n-1\) 个,那么最终序列一定长成 \(abab\ldots ababbaba\ldots ba\) 或 \(abab\ldots ab\) 或 \(baba\ldots ba\) 的样子。
于是我们的贪心策略是,先依次放 \(ab\),要求每个 \(i\) 都满足 \(b_i > a_{i+1}\),如果能放完则显然满足条件。如果存在一个 \(i\) 满足 \(b_i < a_{i+1}\),那么就从 \(i+1\) 开始都放 \(ba\),对于后面的所有 \(i\) 就都要满足 \(b_i > a_{i-1}\)。这样贪心一定是对的,如果某个方案不是从第一次满足 \(b_i < a_{i+1}\) 的位置开始放 \(ba\) 而是提前放,那么一定可以调整为上述贪心策略。
于是我们分两种情况讨论,第一种是不存在 \(b_i < a_{i+1}\),即序列为 \(abab\ldots ab\),考虑用插入法计数。我们将所有二元组按 \(b_i\) 排序再倒着依次插入,如果一个 \((a_i,b_i)\) 插到了满足 \(b_i<a_j\) 的 \((a_j,b_j)\) 前面那么后面无论怎么插入都不合法,于是每个 \((a_i,b_i)\) 只能插在满足 \(b_i>a_j\) 的 \((a_j,b_j)\) 前面或序列末尾。设 \(f_i\) 表示有多少个 \(j\) 满足 \(b_j>b_i>a_j\),那么这部分的方案数为 \(\prod (f_i+1)\)。
接下来考虑第二种情况,假设交界处为 \((a_x,b_x),(b_y,a_y)\)(这里的二元组均为按 \(b_i\) 排序后的),则需要满足 \(a_y>b_x\)。同样使用插入法,我们将剩余二元组按 \(b_i\) 从大到小依次插入。那么对于 \(>y\) 的 \(i\),可以插在 \(f_i\) 个位置和 \((b_y,a_y)\) 后、\((a_x,b_x)\) 前,即方案数为 \(f_i+2\)。同理可得,对于 \(x<i<y\),方案数为 \(f_i+1\),对于 \(i<x\),方案数为 \(f_i\)。也就是说总的答案为:
直接做复杂度为 \(\mathcal{O}(n^3)\),记录 \(f_i\) 的前缀积 \(s1_i\)、\(f_i+1\) 的后缀积 \(s2_i\),\(f_i+2\) 的后缀积 \(s3_i\),那么一个 \(x,y\) 的答案就是 \(s1_{x-1}\times \frac{s2_{x+1}}{s2_y}\times s3_{y+1}\)。此时我们枚举 \(y\),合法的 \(x\) 是一段前缀,再记录 \(s1_{i-1}\times s2_{i+1}\) 的前缀和即可。复杂度为 \(\mathcal{O}(n\log n)\),精细实现可以做到 \(\mathcal{O}(n)\)。
Submission #70882051 - AtCoder Grand Contest 053
[AGC053F] ESPers
有 \(2n+1\) 个人参与投票,其中 \(k\) 个为 ESPer,其余为普通人,所有人会在两个选项中投票,最后所有投最终票数多的选项的人获胜。投票共有 \(2n+1\) 轮,每轮过程如下:
- 从所有还未投过票的人中随机选择一个进行投票。
- 如果这个人是普通人,则会在两个选项中随机投一个。否则如果是 ESPer,则会给当前票数多的选项投票,如果两个选项票数一样多,则会随机投一个。
X 是其中某个 ESPer,求 X 获胜的概率。
答案对 \(998244353\) 取模。\(k\le 2n+1,n\le 2\times 10^6\)。
牛逼题。
直接 dp 可以得到一个 \(\mathcal{O}(n^3)\) 的做法,但是没有什么前途。
先考虑一个牛逼转化,我们观察 X 投票后有没有出现两个选项平票的情况(包括 X 刚投票完),如果出现了,那么两个选项就变成等价的了,即 X 获胜的概率为 \(50\%\),否则 X 投的选项会一直领先到最后,即 X 获胜。于是我们求出 X 投票后出现平局的概率 \(p\),答案就是 \(1-\frac p 2\)。
继续转化,设 \(1\) 表示一个人投给了票数更多的选项,\(-1\) 表示投给了更少的选项,如果平票就将 \(1\) 看成投给第一个选项,\(-1\) 看成第二个选项。于是每个普通人就是在 \(1,-1\) 之间随机,而 ESPer 一定是 \(1\),我们考虑用 X 投票后有平局的方案数除以总方案数来计算 \(p\),那么每个方案就是先决定普通人和 ESPer 之间的顺序,再决定每个普通人是 \(1\) 还是 \(-1\),于是总方案数为 \({2n+1\choose k}2^{2n+1-k}\)。
现在我们相当于枚举所有长度为 \(2n+1\) 且由 \(1,-1\) 构成的序列,然后找到最后一次平票的位置,而 X 可能是这些 \(1\) 中的任意一个,所以贡献为最后一次平票的位置前面 \(1\) 的个数除以总的 \(1\) 的个数,然后我们还要决定每个人是否是 ESPer,于是还要乘上 \({cnt_1\choose k}\)。
考虑优化这个枚举过程,我们可以将 \(1,-1\) 看成是两个票数之差的变化量,但是当平票时再取 \(-1\) 就不对,我们可以将这些时刻的 \(-1\) 都拉出来考虑。将 \(1\) 看成左括号,\(-1\) 看成右括号,把这个序列看成括号序列。将这个括号序列中所有没被匹配的括号拉出来,那么括号序列一定可以写成 \(S_1)S_2)\ldots S_x)S_{x+1}(S_{x+2}(\ldots (S_{x+y+1}\) 的形式,其中 \(S_i\) 表示一个合法括号序列,考虑这样一个括号序列的贡献。
我们已经确定了 \(x\) 个右括号和 \(y\) 个左括号,那么需要保证 \(x+y\) 是奇数,设 \(t=\frac{2n+1-x-y}{2}\),则剩下的位置中左右括号都恰好有 \(t\) 个,那么 \(1\) 的数量,即左括号的数量就是 \(t+y\),所以有贡献 \(t+y\choose k\)。接下来考虑这个括号序列最后一次平票是什么时候,可以发现每出现两次没配对的右括号就会有一次平票,而后面没配对的左括号不会再发生平票。所以当 \(x\) 是偶数时,最后一次平票是 \(S_{x+1}\) 的末尾处,否则是 \(S_x\) 的末尾处。
考虑计算 X 是最后一次平票前的某个 \(1\) 的概率。因为所有 \(S_i\) 中共有 \(t\) 个 \(1\),那么每个 \(S_i\) 中期望有 \(\frac{t}{x+y+1}\) 个 \(1\),最后一次平票是 \(S_{x+[2\mid x]}\) 结尾处,那么最后一次平票前期望有 \((x+[2\mid x])\frac{t}{x+y+1}\) 个 \(1\)。而总共有 \(t+y\) 个 \(1\),所以 X 是最后一次平票前的某个 \(1\) 的概率为 \(\frac{(x+[2\mid x])t}{(x+y+1)(t+y)}\)。
最后我们还要计算有多少个括号序列长成 \(S_1)S_2)\ldots S_x)S_{x+1}(S_{x+2}(\ldots (S_{x+y+1}\) 的样子,可以看成计数 \((\ldots((S_1)S_2)\ldots S_{x+y})\) 形式的括号序列数量,相当于从 \((x+y,0)\) 走到 \((t+x+y,t+x+y)\) 并且不跨过 \(y=x\) 这条直线的路径数,即 \({2n+1\choose t}-{2n+1\choose t-1}\)。于是最终答案就是:
于是我们可以在 \(\mathcal{O}(n^2)\) 的复杂度内计算。接下来考虑优化,可以发现式子中大部分东西都和 \(x+y\) 有关,于是我们枚举 \(s=x+y\),除去只和 \(s\) 有关的式子,剩下要计算的就是:
设 \(f_i = \frac{i\choose k}{i}\),现在要算的就是 \(\sum\limits_{x=0}^s f_{t+s-x}(x+[2\mid x])\),再拆成 \(\sum\limits_{x=0}^s f_{t+s-x} x\) 和 \(\sum\limits_{x=0}^s f_{t+s-x}[2\mid x]\) 两部分计算,那么只需维护 \(f_i\) 的前缀和、\(f_i\times i\) 的前缀和、\(f_i\) 隔一位的前缀和即可 \(\mathcal{O}(1)\) 计算每个 \(s\) 的答案。总复杂度为 \(\mathcal{O}(n)\)。
Submission #70904350 - AtCoder Grand Contest 053
AGC052
[AGC052A] Long Common Subsequence
\(n\) 个 0 加 \(n\) 个 \(1\) 加 \(0\) 即可。Submission #70653082 - AtCoder Grand Contest 052
[AGC052B] Tree Edges XOR
给定一棵 \(n\) 个点的树,\(n\) 为奇数。每条边有初始边权 \(w_1\) 和目标边权 \(w_2\),你可以执行任意次一下操作:
- 选择一条边 \((u,v)\),设当前权值为 \(w\),将所有恰与 \(u,v\) 其中一个点相连的边的权值异或 \(w\)。
求是否能将所有边的边权变为目标边权。
\(n\le 10^5,w_1,w_2\le 10^9\)
可以发现一次操作是将所有与 \(u\) 相连的边异或 \(w\),\(v\) 同理,这样 \((u,v)\) 边权不变,于是可以设一个 \(s_u\) 表示与 \(u\) 相连的边异或了多少。但一开始还有初始边权,于是我们任意钦定一个 \(s_u\) 为 \(0\),就能求出其他所有 \(s\),使得每条边 \((u,v)\) 的边权一直都是 \(s_u\oplus s_v\)。那么一次操作就是将 \(s_u,s_v\) 同时异或上 \(s_u\oplus s_v\),即交换 \(s_u,s_v\)
那么相当于我们可以任意交换 \(s\) 中的数,同理任意钦定一个 \(s'_u\) 为 \(0\),求出关于 \(w_2\) 的 \(s'\),则要求 \(s\) 和 \(s'\) 构成的可重集相同。但注意我们将 \(s\) 中所有数全部异或一个 \(x\) 边权是不变的,相当于条件是存在一个 \(x\) 使得 \(s\oplus x\) 与 \(s'\) 构成的可重集相同,因为 \(n\) 是奇数,所以 \(x\) 一定为 \(s\) 中所有元素异或 \(s'\) 中所有元素,得到 \(x\) 后再判断集合是否相同即可。
Submission #70653564 - AtCoder Grand Contest 052
[AGC052C] Nondivisible Prefix Sums
给定质数 \(p\) 和 \(n\),定义一个长为 \(n\) 的正整数序列 \(a\) 是好的,当且仅当存在一种 \(a\) 的重排方式,使得 \(a\) 的任意一个非空前缀和都不是 \(p\) 的倍数。求有多少个长为 \(n\) 的好的序列,满足每个元素都在 \([1,p-1]\) 之间。
答案对 \(998244353\) 取模。\(n\le 5000,p\le 10^8\)
考虑如何判断一个 \(a\) 是否是好的,首先肯定要 \(\sum a_i\) 不是 \(p\) 的倍数。考虑一个一个加数,可以发现,如果 \(a\) 中所有数互不相同,那么一定合法,因为两个不同的数中一定有一个满足加入后序列和不为 \(p\) 的倍数。但如果全是同一个数 \(x\),加入 \(p\) 次后一定会是 \(p\) 的倍数,所以可以感性理解条件是数不能太单一。
我们假设 \(a\) 的众数是 \(1\),如果不是,设为 \(x\),将所有数乘上 \(x\) 在模 \(p\) 意义下的逆元,条件依然相同。现在 \(1\) 有很多,那就是能放 \(1\) 就放 \(1\),不能放时就放一个其他数。首先会放 \(p-1\) 个 \(1\),然后假设放了一个 \(x\),那么又能放 \(p-x\) 个 \(1\),接下来同理。所以其余 \(>1\) 的数具体放什么位置不重要,只需要知道在放了 \(x\) 后还能再放 \(x-1\) 个 \(1\),于是一个必要条件为:\(cnt_1\le p-1+\sum\limits_{a_i>1}p-a_i\)。
接下来我们可以说明这也是个充分条件,考虑以下策略:假设当前众数为 \(x\)(有多个就任取),如果加入 \(x\) 后合法,那么就加入 \(x\),否则找一个与 \(x\) 不同的 \(y\),加入 \(y,x\)。如果这个策略不合法,那肯定是剩下了一种数,并且因为序列和不是 \(p\) 的倍数,那么剩的个数一定 \(>1\)。
可以发现,如果某个数出现次数和另一个数出现次数之差不超过 \(1\),那么之后也一定不会超过 \(1\),但不合法时出现次数之差 \(>1\),相当于这种数一直是众数,也就是一开始的 \(1\)。那么此时执行的策略就是能放 \(1\) 就放否则放其他数,而根据上面的条件,\(1\) 一定会放完,所以矛盾了。于是我们就说明了这是个充要条件。
接下来考虑计数,用 \((p-1)^n\) 减去所有不合法的方案。首先减去和是 \(p\) 的倍数的方案,设 \(g_n\) 表示长为 \(n\) 的序列和为 \(p\) 的倍数的方案,递推式为 \(g_n = (p-1)^{n-1}-g_{n-1}\)。接下来考虑 \(cnt_1>p-1+\sum\limits_{a_i>1}p-a_i\),我们处理出 \(f_{i,j}\) 表示 \(i\) 个 \(>1\) 的数且 \(\sum p-a_i=j\) 的方案数,其中 \(j\) 的上界只需要取到 \(n\),转移是简单的。
因为每个 \(>1\) 的数至少会贡献 \(1\),所以不合法时 \(1\) 一定是绝对众数,于是我们可以枚举 \(1\) 的出现次数,剩下的数任意填即可。假设 \(1\) 出现了 \(i\) 次,\(\sum p-a_i=j\),那么要求序列和不为 \(p\) 的倍数,即 \(i-j\not\equiv0\pmod p\),并且 \(i > p-1+j\),此时贡献为 \((p-1){n\choose i}f_{n-i,j}\)。复杂度 \(\mathcal{O}(n^2)\)。
Submission #70654494 - AtCoder Grand Contest 052
[AGC052D] Equal LIS
给定一个 \(1\sim n\) 的排列 \(p\),求能否将 \(p\) 划分为两个不交的子序列,满足它们的 LIS 长度相同。
\(n\le 2\times 10^5\)
设 \(f_i\) 表示以 \(i\) 结尾的 LIS 长度,\(s\) 表示整个序列的 LIS 长度。如果 \(s\) 是偶数,那么将所有 \(f_i\le \frac s 2\) 的 \(i\) 和 \(f_i > \frac s 2\) 的 \(i\) 划分为两个子序列,这两个子序列的 LIS 长度都是 \(\frac s 2\)。于是只需要考虑 \(s\) 是奇数的情况。
设 \(s=2k+1\),任意找一个原来的 LIS,那么肯定有个子序列包含 LIS 中的至少 \(k+1\) 项,那么另一个子序列至多有 \(k\) 项,所以一定还包含一个原来不在 LIS 中的元素,我们考虑划分为两个 LIS 长度为 \(k+1\) 的子序列。
于是我们枚举这个不在原来 LIS 中的元素 \(x\),要求存在一个长度为 \(k+1\) 的上升子序列包含 \(x\)。那么假设除 \(x\) 外的其他 \(k\) 个元素的 \(f_i\) 形成的集合为 \(S\),我们将所有 \(f_i\in S\) 的 \(i\) 和 \(x\) 划分到一起,那么这个子序列的 LIS 长度一定为 \(k+1\),因为存在一个长度为 \(k+1\) 的上升子序列并且 \(f_i\) 只有 \(k+1\) 种。其余的数划分到另一个子序列,同理 LIS 长度为 \(k+1\) 于是我们就完成了一种构造。
而如果不存在这样的 \(x\),就意味着任意去掉 LIS 中的 \(k+1\) 项,剩下的数的 LIS 长度都 \(\le k\),那么一定无解。再记一个 \(g_i\) 表示以 \(i\) 开头的 LIS 长度,只需判断 \(f_i+g_i-1\ge k+1\) 的个数是否 \(>s\) 即可。复杂度 \(\mathcal{O}(n\log n)\)。
Submission #70655046 - AtCoder Grand Contest 052
[AGC052E] 3 Letters
定义一个由 ABC 组成的字符串 \(S\) 是好的,当且仅当 \(S\) 任意相邻两个字母都不同。给定长度为 \(n\) 的好的字符串 \(S,T\),每次操作可以更改 \(S\) 中的某个字符,要求更改后 \(S\) 也是好的,求将 \(S\) 变成 \(T\) 最少需要多少次操作。
\(n\le 5\times 10^5\)
AGC059E 的套路。将 ABC 分别看成 \(0,1,2\),考虑给每个 \(S_i\) 赋一个权值 \(a_i\),满足 \(a_i\equiv S_i\pmod 3\) 并且任意两个相邻的 \(a_i\) 相差 \(1\)。不妨设 \(a_1 = S_1\),那么剩下的 \(a_i\) 都可以算出来,那么每次操作就是给 \(a_i\pm 2\),并且依然要满足相邻的 \(a_i\) 相差 \(1\),最终我们要将 \(a_i\) 变得满足 \(a_i\equiv T_i\pmod 3\)。
假设我们知道了 \(a_i\) 最终要变成 \(b_i\),求最少需要多少次操作。首先要求每个 \(i\) 都满足 \(a_i,b_i\) 同奇偶,那么有个显然的下界为 \(\sum\frac{|a_i-b_i|}2\),接下来我们证明一定能取到这个下界,相当于每次操作一定存在一个 \(a_i\) 可以向 \(b_i\) 靠近 \(2\)。
设 \(d_i = a_i-b_i\),那么一定不能有一正一负的 \(d_i\) 相邻,不然它们的 \(d_i\) 一定相差不止 \(1\)。于是考虑所有 \(d_i=0\) 将序列划分为了若干段,每段之间一定 \(d_i\) 全为正或负。如果全为正,那么选择 \(d_i\) 最小的操作一定合法,全为负选择最大值一定合法。于是我们就说明了每次一定存在合法的操作。
接下来还是设 \(b_1 = T_1\) 求出整个 \(b\) 序列,如果 \(a_1,b_1\) 不同奇偶就让所有 \(b_i\) 都 \(+3\),那么最终的 \(a\) 序列一定是 \(b\) 每个数同时加上或减去 \(6\) 的倍数得到的。设 \(d_i = a_i-b_i\),我们就是要求一个整数 \(x\) 满足 \(\sum |d_i+6x|\) 最小,将 \(d\) 排序后枚举最后一个 \(<0\) 的元素是哪个即可。复杂度 \(\mathcal{O}(n\log n)\),也可以通过找中位数然后微调做到 \(\mathcal{O}(n)\)。
Submission #70656645 - AtCoder Grand Contest 052
AGC049
[AGC049A] Erasing Vertices
skip。Submission #69916441 - AtCoder Grand Contest 049
[AGC049B] Flip Digits
skip。Submission #69916264 - AtCoder Grand Contest 049
[AGC049C] Robots
skip。Submission #69917125 - AtCoder Grand Contest 049
[AGC049D] Convex Sequence
给定 \(n,m\),求有多少个长为 \(n\) 的非负整数序列 \(a\) 满足:
- \(\sum a_i = m\)
- \(\forall 1 < i < n\),满足 \(2a_i\le a_{i-1}+a_{i+1}\)
答案对 \(10^9+7\) 取模。\(n,m\le 10^5\)
将第二个条件移项得 \(a_i-a_{i-1}\le a_{i+1}-a_i\),也就是说差分数组不降,即 \(a\) 是下凸的。那么找到 \(a\) 中最小值所在段,两边的长度是 \(\mathcal{O}(\sqrt n)\) 级别的。于是我们可以考虑枚举最小值所在位置 \(x\),如果有多个就取最左边的,求这种情况下的答案。先假设最小值为 \(0\)。
对于 \(x\) 右侧,我们相当于任意确定一个二阶差分数组 \(d\),要求每个元素非负,那么将 \(d_{n-i+1}\) 加一会让整个 \(a\) 的和加上 \(\frac{i(i+1)}2\),相当于在做完全背包。对于 \(x+1\sim n\) 这些位置都可以让 \(d_i\) 加一,也就是说我们有体积为 \(1,3,\ldots,\frac{(n-x)(n-x+1)}{x}\) 这些物品。左侧同理,有 \(1,3,\ldots,\frac{(x-1)x}2\),但要注意因为 \(x\) 是最左边的最小值,即 \(a_{x-1}>a_x\),所以一定会选一次物品 \(\frac{(x-1)x}2\)。
因为我们一开始设的是最小值为 \(0\),如果不为 \(0\) 可以看成是由最小值是 \(0\) 进行全体 \(+1\) 操作得到的,相当于还有一个体积为 \(n\) 的物品,答案就是由这些物品做完全背包凑体积为 \(m\) 的方案数。因为两侧都至多有 \(\sqrt m\) 个物品,所以对单个 \(x\) 求解的复杂度为 \(\mathcal{O}(m\sqrt m)\)。
但我们不能对每个 \(x\) 都这么算,可以发现,对于相邻两个 \(x\),它们做背包相差的物品最多只有两个。相当于是完全背包支持删除和加入物品,加入是好做的,删除时将要删的物品当作是最后加入的然后倒着减一便即可。并且 \(x\) 最大值也是 \(\mathcal{O}(\sqrt m)\) 级别的,所以总复杂度为 \((m\sqrt m)\)。
Submission #69918259 - AtCoder Grand Contest 049
[AGC049E] Increment Decrement
定义一个长度为 \(n\) 的正整数序列 \(b\) 的权值为,初始时有一个长度为 \(n\) 的全 \(0\) 的序列 \(a\),用以下操作使得 \(a\) 变成 \(b\) 的最小代价:
- 选择一个 \(i\) 和 \(x\in\{-1,1\}\),\(a_i\larr a_i+x\),代价为 \(1\)。
- 选择一个区间 \([l,r]\) 和 \(x\in\{-1,1\}\),对所有 \(i\in [l,r]\),\(a_i\larr a_i+x\),代价为常数 \(C\)。
现在给定 \(n\) 个长度为 \(k\) 的正整数序列 \(B_1,\ldots,B_n\),将每个 \(b_i\) 赋为 \(B_i\) 中的任何一个数,求在 \(k^n\) 种方案中,\(b\) 的权值之和是多少。
答案对 \(998244353\) 取模。\(C\le n\le 50,k\le 50\)
做法一:
考虑求一个 \(b\) 的代价,首先发现区间 \(-1\) 操作一定不优,证明可以使用调整法。我们把所有 \(b_i\) 画成一个柱状图,那么我们可以把每一层分开考虑,即求出每一层的答案再加起来,因为一定可以通过调整操作顺序使得每次操作都是在同一层上进行。
接下来对于一层,相当于我们只需要考虑 \(b\) 中只有 \(01\) 的答案。设 \(f_i\) 表示 \(b_1,\ldots,b_i\) 的答案,设 \(s_i\) 表示 \(!b_i\) 的前缀和,分覆盖 \(b_i\) 的是单点还是区间来考虑,如果是区间那么就枚举区间的左端点 \(l\),即:
因为最多有 \(n\) 个本质不同的层,将 dp 使用前缀和优化即可做到 \(\mathcal{O}(n^2)\) 求解一个 \(b\) 的代价。接下来考虑原问题,可以发现,如果将所有 \(B_{i,j}\) 排序,那么本质不同的层最多有 \(nk\) 种。假设排序后数组为 \(a_i\),我们求出所有序列第 \(a_i\) 层的代价,再乘上 \(a_i-a_{i-1}\) 贡献给答案。
求第 \(a_i\) 层的代价,相当于将 \(\ge a_i\) 的数设为 \(1\),其余设为 \(0\),然后 \(b_i\) 从 \(B_i\) 中任选一个做上述 dp。于是我们可以将原来的 dp 状态放进 dp 里面,即设 \(F_{i,j,k}\) 表示前 \(i\) 个数,\(f_i=j\),\(C+s_i-s_{j-1}+f_{j-1}\) 的最小值为 \(k\) 的方案数,转移时枚举下个是 \(0\) 还是 \(1\),可以 \(\mathcal{O}(1)\) 转移。复杂度为 \(\mathcal{O}(n^4k)\)。
Submission #69919473 - AtCoder Grand Contest 049
做法二:
还是考虑求一个 \(b\) 的代价,我们设 \(f_{i,j}\) 表示考虑了前 \(i\) 个数,有 \(j\) 个区间覆盖到了 \(i\) 的最小代价。转移为:
可以考虑 slope trick,每个的 \(f_i\) 都是一个凸包,初始时 \(f_{0,j} = Cj\)。每次到 \(i\) 时,进行 \(f_{i,j} = \min\limits_{k\ge j} f_{i-1,k}\) 的操作相当于是将前面斜率 \(<0\) 的部分推平,进行 \(f_{i,j} = \min\limits_{k\le j} f_{i-1,k}+C(j-k)\) 的操作相当于将最后斜率 \(>k\) 的部分推平为斜率为 \(k\)。套路地,我们维护一个 multiset,其中每个元素 \(x\) 表示斜率在 \(x\) 处增加 \(1\),初始时放 \(C\) 个 \(0\)。最终答案为凸包开头位置的真实值。
对于每个 \(i\),考虑先进行加 \(|b_i-j|\) 的操作再进行推平操作,因为 \(i=1\) 时的推平操作可以忽略所以这样是等价的。对每个 \(j\) 加上 \(|b_i-j|\) 相当于放两个 \(b_i\) 进入 multiest,并且凸包开头会加上 \(|b_i-s.begin()|\),因为放入了 \(b_i\) 所以开头一定 \(\le b_i\),所以令答案加上 \(b_i-s.begin()\)。此时一定满足开头一段斜率为 \(-1\),结尾一段斜率为 \(k+1\),所以弹出 multiset 的开头和结尾。于是可以做到单次 \(\mathcal{O}(n\log n)\) 求解,代码如下:
ll solve()
{
ll ans = 0;multiset<int> s;
for(int i = 1;i <= C;i++)s.insert(0);
for(int i = 1;i <= n;i++)
{
s.insert(b[i]);s.insert(b[i]);
ans += b[i]-*s.begin();
s.erase(s.begin());s.erase(prev(s.end()));
}
return ans;
}
接下来考虑原问题,即统计所有 \(b_i-s.begin()\) 的和,首先 \(b_i\) 是好算的,每个 \(B_{i,j}\) 都会贡献 \(k^{n-1}\) 次。接下来考虑 \(s.begin()\) 之和,可以发现 \(s.begin()\) 最多有 \(nk\) 种取值,于是我们可以统计每种取值 \(x\) 出现了多少次,差分一下变为 \(\ge x\) 出现了多少次减去 \(>x\) 出现了多少次,那么每个数就可以根据和 \(x\) 的关系看成 \(01\) 了。
设 \(f_{i,j}\) 表示考虑完前 \(i\) 个数后,multiset 中有 \(j\) 个 \(1\) 的方案数。转移是简单的,复杂度为 \(\mathcal{O}(n^2kc)\)。

浙公网安备 33010602011771号