AGC VP 记录 3

AGC VP 记录

AGC021~AGC040

AGC040

[AGC040C] Neither AB nor BA

奇数位 AB 反转,合法条件为 \(A,B\) 的出现次数不超过 \(\lfloor\frac n 2\rfloor\),容斥计算即可。Submission #72974725 - AtCoder Grand Contest 040

[AGC040D] Balance Beam

\(n\) 个平台,每个平台长一米,小 A 和小 B 在第 \(i\) 个平台的速度分别为 \(\frac 1 {a_i},\frac 1 {b_i}\) 米每秒,你可以以任意顺序将 \(n\) 个平台横向连接,最大化以下值:

  • 小 A 初始在最左边出发,小 B 初始在 \([0,n]\) 中随机一个点,两人同时出发,小 A 在小 B 到达最右边前追上小 B 的概率。

\(n\le 10^5,a_i,b_i\le 10^9\)

有点抽象。

考虑知道平台顺序怎么求答案,显然小 A 能追上小 B 时小 B 的起点是一段前缀,考虑求出最大的起点 \(x\)。假设小 B 从最左边出发,在以 \(x\) 轴为时间、\(y\) 轴为到最左端的距离的二维平面上画出两人的轨迹,将小 B 的折线不断往下平移使得两人的折线始终有交点,一直移到不能再动,此时小 B 的折线与 \(x\) 轴的截距就是答案。

接下来考虑我们关注两段折线的哪些东西,首先小 B 的折线会经过 \((x,0)\),然后小 B 的折线会与小 A 的折线交与某个点,最后小 A 的折线会走到 \((n,\sum a_i)\)。并且我们只需要关心这条经过 \((x,0)\)、交点、\((n,s_n)\) 的折线,也就是说只需确定 \(x\)\(x\) 到交点一段的 \(b_i\) 集合,交点到 \((n,\sum a_i)\) 一段的 \(a_i\) 集合,剩余部分任意排序即可。如果在交点前后两条折线还有其余交点显然不优。

显然交点的横坐标一定是整数,不然一定不优,枚举 \((x,0)\) 所在的平台 \((a_p,b_p)\)。因为我们要让 \(x\) 尽量大,所以要让 \((x,0)\)、交点、\((n,\sum a_i)\) 这条折线的宽度尽量小,也就是斜率尽量大。而对于一个平台 \((a_i,b_i)\) 斜率最大为 \(\max(a_i,b_i)\),于是将所有平台按 \(\max(a_i,b_i)\) 从大到小排序,然后取一个前缀 \(l\) 使得 \(b_p+\sum\limits_{i=1}^l \max(a_i,b_i)\ge \sum a_i\) 即可。

为什么后面一定能取到斜率最大值?我们将前 \(l\)\((a_i,b_i)\)\(b_i > a_i\) 的放在 \(b_i\le a_i\) 的前面,那么交点取 \(b_i > a_i\)\(b_i\le a_i\) 的分界点即可。枚举 \(p\),二分求出 \(l\),然后算出答案,将所有答案取最大值即可。复杂度 \(\mathcal{O}(n\log n)\)

[AGC040E] Prefix Suffix Addition

给定一个长为 \(n\) 的正整数序列 \(a\),有一个长为 \(n\) 的序列 \(x\),初始时所有 \(x_i=0\),你可以不断进行以下两种操作:

  • 选择一个单调不降序列 \(c_1,\ldots,c_k\),对所有 \(1\le i\le k\),将 \(a_i\) 加上 \(c_i\)
  • 选择一个单调不升序列 \(c_1,\ldots,c_k\),对所有 \(1\le i\le k\),将 \(a_{n-k+i}\) 加上 \(c_i\)

求使得所有 \(x_i=a_i\) 的最小操作次数。

\(n\le 2\times 10^5,a_i\le 10^9\)

考虑只有第一种操作怎么做,显然每次操作最多增加一个满足 \(x_i>x_{i+1}\)\(i\),所以答案的下界为 \(\sum\limits_{i=0}^n[a_i>a_{i+1}]\)(设 \(a_0=a_{n+1}=0\)),并且这个下界可以取到,所有 \(a_i > a_{i+1}\)\(i\) 将整个序列划分为了若干段单调不降序列,每次加一段即可。同理如果只有第二种操作,答案为 \(\sum\limits_{i=0}^n[a_{i-1}<a_i]\)

设第二种操作对 \(x_i\) 的贡献为 \(b_i\),于是对一个序列 \(b\) 的代价为 \(\sum\limits_{i=0}^n [b_i<b_{i+1}]+[a_i-b_i < a_{i+1}-b_{i+1}]\),其中要求 \(0\le b_i\le a_i\),于是可以用 dp 来解决。设 \(f_{i,j}\) 表示考虑了 \(b_i=j\) 的最小代价,转移为:

\[f_{i,j} = \min_{k=0}^{a_{i-1}}f_{i-1,k}+[j>k]+[j>k+a_i-a_{i-1}] \]

对于一个 \(f_{i-1,k}\),它对整个 \(f_i\) 的贡献是一个不降的首尾差不超过 \(2\) 的折线,而对所有 \(f_{i-1,k}\) 的折线对位取最小值也是这个形态,即所有 \(f_i\) 都是一个不降的极差不超过 \(2\) 的折线,于是我们维护出两个拐点以及 \(f_{i,0}\) 是多少即可。转移直接模拟转移式子即可,复杂度为 \(\mathcal{O}(n)\)

Submission #74449833 - AtCoder Grand Contest 040

AGC039

[AGC039D] Incenters

怎么还出平面几何,看洛谷题解吧。Submission #74383649 - AtCoder Grand Contest 039

[AGC039E] Pairing Points

一个圆周上有 \(2n\) 个点,按顺序依次编号为 \(1\sim 2n\),此外给定一个 \(2n\times 2n\) 的矩阵,求将 \(2n\) 个点划分为 \(n\) 对点的方案数,要求满足:

  • 将每对点用线段连起来,所有线段构成一棵树。
  • 对于每对匹配的点 \((x,y)\),要求 \(a_{x,y} = 1\)

\(n\le 20\)

可以手玩一下,发现我们只需要关心如下子问题:\(f_{l,r,k}\) 表示只考虑编号为 \(l\sim r\) 中的点,其中点 \(k\) 连向了区间外的一个点的方案数。初始化为 \(f_{i,i,i} = 1\),求最终答案就是枚举 \(1\) 与点 \(u\) 配对,贡献为 \(f_{2,n,u}\)

考虑求解 \(f_{l,r,k}\),其中 \([l,k)\)\((k,r]\) 之间会依次有若干条连边,这些连边会划分出若干个区间,然后还要将每个区间从中间划开分给左右两条边,并递归到子问题。枚举最外面的连边 \((x,y)\),其中 \(l\le x < k < y\le r,a_{x,y} = 1\),接着枚举左边分到了区间 \([l,p]\),右边分到了区间 \([q,r]\),则转移为:

\[f_{l,r,k}\larr f_{p+1,q-1,k}\times f_{l,p,x}\times f_{q,r,y} \]

直接做是 \(\mathcal{O}(n^7)\),但是跑的飞快,可以优化到 \(\mathcal{O}(n^5)\)

Submission #74384142 - AtCoder Grand Contest 039

[AGC039F] Min Product Sum

有一个大小为 \(n\times m\),每个数在 \([1,k]\) 内的矩阵 A,定义 \(f(x,y)\) 表示第 \(x\) 行和第 \(y\) 列共 \(n+m-1\) 个数中的最小值。定义矩阵 A 的权值为 \(\prod\limits_{x=1}^n\prod\limits_{y=1}^m f(x,y)\)。你需要求出所有 \(k^{nm}\) 个矩阵的权值和。

答案对给定质数取模。\(n,m,k\le 100\)

如果一个大小为 \(n\times m\),每个数在 \([1,k]\) 内的矩阵 B 满足 \(\forall x,y,B_{x,y}\le f(x,y)\),那么答案就是计数有多少个 \((A,B)\) 这样的矩阵对。

考虑 \(\forall x,y,B_{x,y}\le f(x,y)\) 这个条件相当于什么,即 \(A\) 每一行的所有数都大于等于 \(B\) 对应这一行中的数,即 \(A\) 这一行的最小值大于等于 \(B\) 这一行的最大值,列同理。接下来考虑怎么计数,如果你注意力惊人,那么就有一个很牛的 dp:

我们从值域上考虑,依次枚举 \(1\sim k\),然后将 \(A\) 其中一些列的 \(\min\)\(B\) 其中一些行的 \(\max\) 设为 \(k\),并确定一些位置的取值。设 \(f_{t,i,j}\) 表示考虑了值域 \(1\sim t\)\(A\) 确定了 \(i\) 列的 \(\min\)\(B\) 确定了 \(j\) 行的 \(\max\) 的方案数。

假设当前枚举的值为 \(x\),我们先考虑将 \(B\) 的某一行的 \(\max\) 赋为 \(k\),然后考虑哪些位置的值的范围能被确定。首先对于矩阵 A,要求 A 中对应这一行的 \(\min\ge k\),即所有数都 \(\ge k\)。对于 A 中还未确定 \(\min\) 的列,因为这些数的 \(\min\) 还未确定,所以一定都 \(\ge k\),先暂时不考虑。对于那些已经确定了 \(\min\) 的列,我们一定可以确定这些数的范围在 \([x,k]\),于是方案数为 \((k-x+1)^i\)

对于 \(B\),如果一列之前已经确定了最小值,那么这个位置一定 \(<k\),所以不会造成影响。于是就要求剩下 \(m-i\) 个位置的 \(\max=k\),方案数为 \(k^{m-i}-(k-1)^{m-i}\)

然后考虑确定了 \(A\) 的一行 \(\min=k\),先考虑 \(A\),仍然用上面的分析方法,得出要求 \(A\)\(j\) 个位置 \(\min=k\),于是方案数为 \((k-x+1)^j-(k-x)^j\)。B 中则要求 \(n-j\) 个位置要 \(\le n-j\),方案数为 \(x^{n-j}\)

这个时候 dp 就做完了,我们每次在 A 中一个位置两次被覆盖的时候计算这个位置的取值方案,在 B 中一个位置第一次被覆盖时计算。转移的时候把一行或一列变成枚举 \(p\) 行或 \(p\) 列,总复杂度为 \(\mathcal{O}(n^4)\)

Submission #64216499 - AtCoder Grand Contest 039

AGC038

[AGC038E] Gachapon

有一个随机数生成器,每次会生成一个 \(1\sim n\) 的整数,给定长为 \(n\) 的序列 \(a,b\),每次生成整数 \(i\) 的概率为 \(\frac{a_i}{\sum a_j}\),求对于每个 \(i\) 都满足 \(i\) 至少被生成了 \(b_i\) 次的期望操作次数。

答案对 \(998244353\) 取模。\(n,\sum a_i,\sum b_i\le 400\)

如果 \(b_i=1\) 就是经典的 min-max 反演。这道题依然考虑 min-max 反演,问题变为了求集合 \(S\) 内任意一个数满足条件的期望次数。因为我们不关心 \(S\) 以外的数,而一次操作涉及到 \(S\) 内的数的概率为 \(\frac{\sum\limits_{i\in S}a_i}{\sum a_i}\),所以可以求出只考虑 \(S\) 内的数的结果,对答案的贡献为 \(\frac{\sum a_i}{\sum\limits_{i\in S}a_i}\)

转化后的好处是整个问题从无限的变为有限的了,考虑枚举所有可能生成的序列 \(a_1,\ldots,a_k\),满足 \(a_k\) 出现了 \(b_{a_k}\) 次,除 \(a_k\) 外的其它数 \(x\) 都出现了 \(<b_x\) 次,这样子一个序列的贡献为每个 \(a_i\) 被生成的概率之积。

考虑优化,我们实际上只关心 \(S\) 中每个数的出现次数 \(c_i\),枚举序列 \(c\),其中恰好有一个 \(x\) 满足 \(c_x=b_x\),其余满足 \(c_i<b_i\)。设 \(p_i\) 表示 \(i\) 的生成概率,即 \(\frac{a_i}{\sum\limits_{j\in S}a_j}\),则贡献为 \(\frac{((\sum c_i)-1)!}{\prod (c_i-[c_i=b_i])!}\times \prod p_i^{c_i}\),即可重集排列计数。

可以发现我们最终只关心在 \(S\) 内的 \(a_i\) 之和,还有 \(S\) 内的 \(c_i\) 之和。于是可以考虑 dp,设 \(f_{i,j,k,0/1}\) 表示考虑了前 \(i\) 个数,在 \(S\) 内的 \(a_i\) 之和为 \(j\),在 \(S\) 内的 \(c_i\) 之和为 \(k\),是否存在 \(b_i=c_i\)。转移就是对每个 \(i\) 依次看它是否在 \(S\) 内,如果在 \(S\) 内再枚举 \(c_i\) 并乘上对应贡献。复杂度为 \(\mathcal{O}((\sum a_i)(\sum b_i)^2)\)

Submission #74241400 - AtCoder Grand Contest 038

[AGC038F] Two Permutations

给定两个 \(0\sim n-1\) 的排列 \(p,q\),你需要构造两个排列 \(a,b\),满足:

  • \(\forall 1\le i\le n\),满足 \(a_i=i\)\(a_i=p_i\),且 \(b_i=i\)\(b_i=q_i\)

最大化 \(a_i\ne b_i\)\(i\) 的数量,输出这个值。

\(n\le 10^5\)

考虑 \(p\) 的每个置换环,可以发现对于一个置换环的所有位置,要么全部满足 \(a_i=p_i\),要么全部满足 \(a_i=i\)\(q\) 同理。设一个置换环中所有位置 \(a_i=i\) 表示转,\(a_i=p_i\) 表示不转。我们要对 \(p,q\) 中的每个置换环依次决定是否转,即确定若干个 01 变量,来最大化某个值。可以发现这很像最小割模型,而最小割是最小化某个值,所以转成最小化 \(a_i=b_i\) 的个数。

考虑对每个 \(i\) 在什么情况下会有贡献:

  • \(p_i=q_i=i\),则一定有贡献。
  • \(p_i=i,q_i\ne i\),有贡献当且仅当 \(q_i\) 所在环转。
  • \(p_i\ne i,q_i=i\),有贡献当且仅当 \(p_i\) 所在环转。
  • \(p_i\ne q_i,p_i\ne i,q_i\ne i\),有贡献当且仅当 \(p_i,q_i\) 所在环同时转。
  • \(p_i= q_i,p_i\ne i\),有贡献当且仅当 \(p_i,q_i\) 所在环同时转或不转。

最小割模型处理的是两个变量不同时可以用贡献,所以我们将 \(q_i\) 所在环是否转的 01 变量意义取反,于是就可以表示所有贡献了。可以发现连出来的图是单位边权的二分图,跑 dinic 的复杂度为 \(\mathcal{O}(n\sqrt n)\)

Submission #44637545 - AtCoder Grand Contest 038

AGC037

[AGC037D] Sorting a Grid

给定一个 \(n\)\(m\) 列的网格,每个格子里写有一个数,其中 \(1\sim nm\) 每个数恰好出现一次,你需要依次执行以下操作:

  • 重排每一行的数字。
  • 重排每一列的数字。
  • 重排每一行的数字。

最终,你需要使得第 \(i\) 行第 \(j\) 列的格子中写的数为 \((i-1)m+j\),并给出构造。

\(n,m\le 100\)

考虑 mim,将问题转化为有两个矩阵 A、B,其中 A 为给定矩阵,B 为目标矩阵,分别将 A、B 的每行重排,使得 A、B 每列的元素集合相同。对于一个数 \(x\),设其在 \(A、B\) 中所在的行号分别为 \(f_x,g_x\),如果确定 \(x\) 所在的列号 \(y\),则在两个重排后的位置分别为 \((f_x,y),(g_x,y)\)。我们需要给所有 \(x\) 确定 \(y\) 使得 \((f_x,y),(g_x,y)\) 能填满两个矩阵。

可以发现我们只关心每种 \((f_x,g_x)\) 出现了多少个,考虑依次确定两个矩阵的每一列,也就是在剩余的 \((f_x,g_x)\) 中选出 \(n\) 个使得 \(f_x,g_x\) 分别都构成一个排列。

于是考虑网络流建模,源点向 \(n\) 个左部点连流量为 \(1\) 的边,\(n\) 个右部点向汇点连流量为 \(1\) 的边,左部点 \(i\) 向右部点 \(j\) 连流量为 \((i,j)\) 剩余个数的边。跑一次网络流相当于求出一组完美匹配用作第一列,接下来再将所有连向源点和汇点的边流量设为 \(1\),再跑网络流就能求出第二列的答案,重复 \(m\) 次即可。

根据 Hall 定理可知每次一定有解。由于是二分图,复杂度为 \(\mathcal{O}(n^3\sqrt n)\)

Submission #74251454 - AtCoder Grand Contest 037

[AGC037E] Reversing and Concatenating

给定一个长为 \(n\) 的字符串 \(S\),进行 \(k\) 次操作:

  • \(T = S+rev(S)\),从 \(T\) 中选择一个长为 \(n\) 的子串作为新的 \(S\)

求出 \(k\) 次操作后的可能的字典序最小的字符串。

\(n\le 5000,k\le 10^9\)

\(c\)\(S\) 中最小的字符,因为要最小化最终串的字典序,所以显然要最大化最终串开头 \(c\) 的连续段长度。考虑求出这个连续段长度,可以发现一次操作可以让 \(S\) 中某个不在末尾的连续段移到末尾,或者让末尾的连续段长度翻倍并选择放到新串开头还是结尾。

那么对于一段长为 \(len\)\(c\) 连续段,如果不在末尾那么一定是花一次放在末尾,然后每次加倍,最终长度为 \(\min(n,len\times 2^{k-1})\),如果一开始在末尾长度为 \(\min(n,len\times 2^k)\)。也可以考虑直接求出 \(S+rev(S)\) 中最长的 \(c\) 连续段,然后倍长 \(k-1\) 次。

于是 \(k\) 可以直接和 \(\lceil \log_2 n\rceil+1\)\(\min\)。接下来枚举最终串开头的连续段是由最初哪个连续段得到的,如果最终串不是全 \(c\),那么每步的操作都是固定的,所以可以直接对所有连续段求出最终结果并取字典序最小的即可。

我们要取 \(S+rev(S)\) 中一个长为 \(n\) 的子串,然后将末尾的 \(c\) 连续段倍长 \(k-1\) 次,最后将整个串反过来。于是一种简单的写法为设 \(T'=rev(S)+S\),直接取出 \(T'\) 长为 \(n\) 的子串中字典序最小的那个,然后将开头 \(c\) 连续段倍长 \(k-1\) 次即可。因为对于两种方案会先比较开头 \(c\) 个数再比较后面的字符,所以直接按操作前的来比较也是对的。复杂度 \(\mathcal{O}(n^2)\),也可以用 SA 做到 \(\mathcal{O}(n\log n)\)

Submission #74387846 - AtCoder Grand Contest 037

[AGC037F] Counting of Subarrays

有一个常数 L,称一个序列是 \(k\) 级的当且仅当这个序列只有一个数 \(k\),或者可以划分为 \(\ge L\)\(k-1\) 级的序列。现在给定一个长为 \(n\) 的序列 \(a\),求 \(a\) 有多少个子区间满足,存在一个 \(k\) 使得这个区间是 \(k\) 级的。

\(n\le 2\times 10^5,a_i\le 10^9\)

先考虑怎么判断一个序列是否合法,我们把把操作倒过来做,每次相当于可以选择一段长度 \(\ge L\) 的相同的数 \(x\),把这些数合并成一个数 \(x+1\)。那么最优策略就是每次选择序列中最小值所在段,将这个段尽可能的合并,假设这一段长为 \(x\),如果 \(x < L\),那么就不合法,否则就能合并出 \(\lfloor\frac x L\rfloor\) 个数。一直做下去知道序列中只剩一种数,如果此时序列长度为 \(1\) 或者长度 \(\ge L\) 那么就是合法的。

模拟上述做法,每次相当于用 \(\mathcal{O}(L)\) 的代价将序列长度减少 \(L-1\)。枚举次数为线性。我们特判掉最后区间长度为 \(1\) 的情况,这种情况就相当于最开始只有 \(1\) 个数,有 \(n\) 种。于是现在就是求有多少个子区间合并到只有一种数时区间长度 \(\ge L\)

我们还是模拟上述过程,每次合并一段区间,然后计算这个区间内有多少个合法的子区间。合并之后,有可能一个合法的子区间的一个端点在合并的点上另一个不在,这个时候这个区间对答案的贡献就不是 \(1\) 了,而应该有一个权重。于是粗略的想,我们可以给每个点赋一个权重,每次合并点时把权重也合并起来,再计算后面的答案。

具体地,我们对每个点赋两个权值 \(l_i,r_i\),一个合法的子区间 \([i,j]\) 对答案的贡献为 \(l_i\times r_j\),初始时 \(l_i=r_i=1\),每次计算一段区间的代价,这个可以直接前缀和优化求出。然后考虑合并,先考虑 \(r_i\) 的合并,假设这一段有 \(m\) 个数,那么合并后有 \(\lfloor\frac m L\rfloor\) 个数。如果有一个合法的子区间以合并后第一个点作为右端点,那么实际上等价于以原来段中位置 \([L,2L-1]\) 作为右端点,相当于第一个点的 \(r_i\) 等于 \([L,2L-1]\) 中的 \(r_i\) 的和。

于是我们就可以得出,原来段中第 \(i\) 个点的 \(r_i\),应该贡献给合并后第 \(\lfloor\frac i L\rfloor\) 个点的 \(r_i\)。左端点同理,就是从左往右数变成了从右往左数。

于是每次我们就可以合并一个段的同时将 \(l,r\) 也合并出来,然后继续计算即可。注意后面计算有可能会统计到左右端点都在当前合并的区间内的情况,我们要将这些减掉。所以每次是找到最小段,然后加上这段的答案,然后合并这段的点和 \(l_i,r_i\),然后再减去合并后这一段的答案,一直重复下去即可。

每次用堆找到一个最小值所在段,然后合并,总复杂度为 \(\mathcal{O}(n\log n)\)

Submission #65127441 - AtCoder Grand Contest 037

AGC036

[AGC036D] Negative Cycle

给定一个 \(n\times n\) 的正整数矩阵 \(A\),有一张 \(n\) 个点的图,\(\forall 1\le i < n\),有边 \(i\xrightarrow{0}i+1\)\(\forall 1\le i < j\le n\),有边 \(i\xrightarrow{-1}j,j\xrightarrow{1}i\)。删去 \(i\to j\) 的边的代价为 \(a_{i,j}\),注意边权为 \(0\) 的边不能删。求最小的删边代价使得原图不存在负环。

\(n\le 500,a_{i,j}\le 10^9\)

原图不存在负环可以考虑差分约束,即存在一组 \(d_1,\ldots d_n\) 满足所有边的限制。反过来,我们可以枚举所有可能的数组 \(d\),然后删去所有不满足条件的边,取所有数组 \(d\) 得到的删边代价的最小值。因为 \(i\xrightarrow{0}i+1\) 的边不能删,所以一定有 \(d_1\ge d_2\ge \ldots\ge d_n\)

\(d\) 相同数的连续段分别为 \([l_1,r_1],\ldots,[l_k,r_k]\),那么边 \(i\xrightarrow{-1}j\) 不满足条件当且仅当 \(i,j\) 在同一个连续段。接下来要让 \(i<j,a_j > a_i+1\)\((i,j)\) 代价和尽量小,那么相邻两个连续段的 \(d_i\) 相差 \(1\) 一定最优,边 \(i\xrightarrow{1}j\) 不满足条件当且仅当 \(i,j\) 所在的连续段之间至少隔了一个连续段。

接下来就可以 dp 了,设 \(f_{i,j}\) 表示考虑了 \(1\sim i\),最后一个连续段为 \([j,i]\),转移时枚举上一个连续段为 \([k,j-1]\)\(-1\) 边权的贡献为 \((i,j,i,j)\) 的矩形和,\(1\) 边权的贡献为 \((j,i,1,k-1)\) 的矩形和,维护二维前缀和即可 \(\mathcal{O}(1)\) 转移。总复杂度为 \(\mathcal{O}(n^3)\)

Submission #74429074 - AtCoder Grand Contest 036

[AGC036E] ABC String

给定一个只包含字符 ABC 的字符串 \(S\),你需要求出 \(S\) 最长的子序列,满足子序列中相邻的两个位置字符不同,且 ABC 的数量相等。

\(|S|\le 10^6\)

我们考虑一个一个删除 \(S\) 中的字符来得到最长的子序列,首先先将 \(S\) 中相同的字母缩成一段。设三个字母的出现次数分别为 \(C_{A},C_{B},C_{C}\),不妨设 \(C_{A}\le C_{B}\le C_{C}\),那么答案的上限为 \(C_{A}\),于是我们要删除字符使 \(C_{A}=C_{B}=C_{C}\),且删除的字符的数量尽量少。

我们先考虑 \(C_{A}\le C_{B}=C_{C}\) 的情况,这个时候字符串肯定长成 \(CB\ldots BCABC\ldots CBACB\ldots BC\ldots CB\) 这样的形式,即两个 \(A\) 之间有一串 \(BC\ldots BC\),这个时候我们每次删相邻两个 BC 或 CB,那么一定可以删到 \(C_{A}=C_{B}=C_{C}\),于是此时的答案就是 \(C_{A}\)

如果是 \(C_{A}\le C_{B}\le C_{C}\) 的情况,我们目标就是在删除尽量少的 \(A\) 的情况下删除 C 直到 \(C_{A}\le C_{B}=C_{C}\)。于是可以先考虑能否删除每个 C,然后如果仍然没满足条件,就删 AC 或 CA,直到 \(C_{A}\le C_{B}=C_{C}\) 即可,这样一定是最优的。

Submission #64215545 - AtCoder Grand Contest 036

[AGC036F] Square Constraints

给定正整数 \(n\),求满足以下条件的 \(0\sim 2n-1\) 的排列 \(p\) 的个数:

  • \(\forall 0\le i < 2n\),有 \(n^2\le i^2+p_i^2\le (2n)^2\)

答案对给定的数取模。\(n\le 250\)

\((i,p_i)\) 画到平面上,那么两个限制如下图所示:

hanghang

即每个 \(p_i\) 有限制 \(l_i\le p_i\le r_i\),先求出所有 \(l_i,r_i\),可以发现 \(l_i,r_i\) 都是不降的。考虑如果只有 \(p_i\le r_i\) 的限制怎么做,将所有 \(r_i\) 从小到大排序,然后从前往后依次填数,答案为 \(\prod\limits_{i=0}^{2i-1} (r_i+1-i)\)

如果有 \(l_i\) 的限制可以考虑容斥,即钦定 \(x\)\(i\) 满足 \(p_i < l_i\),其余 \(i\) 满足 \(p_i\le r_i\),于是就转化为了上面的问题,贡献为 \((-1)^x\)。但是我们难以处理每个 \(l_i,r_i\) 在所有数中的排名,考虑继续去找性质。可以发现,\(\forall n\le i\le 2n-1\) 都有 \(l_i=0\),也就是说这些 \(i\) 不用容斥。而 \(l_0 = n,r_{n-1}\ge n\),也就是说 \(0\sim n-1\) 中最小的 \(r\) 不小于最大的 \(l\)

我们钦定从小到大排序时如果两个数值相同则按下标降序排。如果只考虑 \(0\sim n-1\) 的答案,因为从后往前考虑时一个 \(r_i\) 的贡献与所有 \(l_i\) 都有关,所以可以先枚举一共钦定 \(x\)\(i\)。设 \(f_{i,j}\) 表示考虑了 \(p_{i\sim n-1}\),其中钦定了 \(j\) 个,那么一个数选 \(l_i-1\)\(r_i\) 的贡献都可以快速算出,最后答案为 \(\sum f_{x,j}(-1)^j\)

接下来考虑 \(n\le i\le 2n-1\)\(i\),在每次上述 dp 每次转移 \(f_{i,j}\) 时要乘上 \(l_{i-1} < r_k\le l_i\) 的贡献,维护一个指针 \(k\) 即可。单次 dp 复杂度 \(\mathcal{O}(n^2)\),总复杂度为 \(\mathcal{O}(n^3)\)

Submission #74772769 - AtCoder Grand Contest 036

AGC035

[AGC035D] Add and Remove

给定一个长为 \(n\) 的自然数序列 \(a\),重复以下操作直到 \(a\) 的长度为 \(2\)

  • 选择 \(a\) 中连续三个数,将左右两个数都加上中间的数,然后删除中间的数。

求剩下两个数之和的最小值。\(n\le 18\)

显然剩下的两个数是原序列的 \(a_1,a_n\)。考虑每个 \(a_i\) 的答案的贡献,首先 \(a_1,a_n\) 的贡献都为 \(1\)。考虑最后一次操作,假设操作的是原序列的 \(a_k\),那么 \(a_k\) 会分别加到 \(a_1,a_n\) 上所以贡献为 \(2\),然后分为 \(1\sim k\)\(k\sim n\) 两个子问题。对于 \(1\sim k\) 这个子问题,还是考虑最后一次操作了 \(a_x\),那么 \(a_x\) 加到 \(a_1,a_k\) 上的贡献分别为 \(1,2\),即 \(a_x\) 贡献为 \(3\)\(k\sim n\) 同理。

于是我们设 \(f_{l,r,x,y}\) 表示考虑删空 \(l\sim r\) 中的数,每次删最左边的数有 \(l\) 的贡献,删最右边的数有 \(r\) 的贡献的最小代价,最终答案为 \(f_{2,n-1,1,1}\),转移为:

\[f_{l,r,x,y} = \min_{k=l}^r a_k\times (x+y)+f_{l,k-1,x,x+y}+f_{k+1,r,x+y,y} \]

直接搜复杂度为 \(\mathcal{O}(3^n)\),加上记搜复杂度为 \(\mathcal{O}(2^npoly(n))\)

Submission #73776652 - AtCoder Grand Contest 035

[AGC035E] Develop

\(S\) 是一个包含了 \(-10^{18}\sim 10^{18}\) 所有整数的不可重集,给定 \(n,k\),你可以进行以下操作若干次:

  • 选择一个 \(1\sim n\) 的整数 \(x\),要求 \(x\in S\),将 \(x\)\(S\) 删去。
  • 如果 \(x-2\not\in S\),将 \(x-2\) 加入 \(S\)
  • 如果 \(x+k\not\in S\),将 \(x+k\) 加入 \(S\)

求若干次操作后能得到多少种不同的 \(S\),答案对给定质数取模。\(k\le n\le 150\)

考虑一个最终的 \(S\) 是否能被得到,倒着操作,每次如果有 \(x-2\in S,x+k\in S\),则将 \(x\) 加入集合 \(S\),显然能加数就加一定最优,\(S\) 合法就是不断加入 \(x\) 后最终能得到全集。

如果 \(x\not\in S\),因为加入 \(x\) 要求 \(x-2,x+k\) 都在 \(S\) 内,如果 \(x-2\not\in S\) 则连边 \(x-2\to x\),如果 \(x+k\not\in S\) 则连边 \(x+k\to x\),一条边 \(u\to v\) 的含义为要加入 \(v\) 则必须先加入 \(u\)。那么一个合法的加入方案就是图的一个拓扑序,所以 \(S\) 合法当且仅当连出来的图不存在环。不妨将计数 \(S\) 变为计数 \(S\) 的补集。

如果 \(k\) 为偶数,则奇偶部分是独立的,考虑求偶数部分的答案,将所有数除以 \(2\)(包括 \(k\)),那么一个 \(S\) 合法当且仅当不存在长为 \(k+1\) 的连续段都在 \(S\) 中,这个可以简单 dp 求出。

如果 \(k\) 为奇数,手玩一下可以发现,如果一个环的最小值和最大值分别为 \(l,r\),那么一定是 \(l\to l+2\to\ldots r\to r-k \to r-k+2\to\ldots\to l+k\to l\)。即环长一定为 \(k+2\),且存在 \(l,r\) 使得 \(l,l+2,\ldots,r\) 都出现过,\(r-k,r-k+2,\ldots,l+k\) 都出现过。

接下来考虑计数,如果直接从小到大依次看每个数是否出现过可能需要记录很多维。不妨将整个图变成如下的构造:

AGC045E-pic

即第 \(i\) 行左边的数位 \(2i-k\),右边的数位 \(2i\),那么一个环一定长成这样:

img

相当于我们把 \(l,l+2,\ldots,r\)\(r-k,r-k+2,\ldots,l+k\) 这两个区间的两个端点对齐了。对于第 \(i\) 行,我们只用关心左部点下面连续选了 \(x\) 个点,右部点上面连续选了 \(y\) 个点,出现环当且仅当 \(x>0,y>0,x+y\ge k+2\)

于是设 \(f_{i,x,y}\) 表示考虑到了第 \(i\) 层,\(x,y\) 含义如上,转移时分别考虑左右部点是否选。对于右部点就是 \(y\) 转移到 \(y+1\)\(0\),左部点如果 \(x>0\) 一定转移到 \(x-1\),否则可以由 \(x=0\) 转移到任意一个非负整数。总复杂度 \(\mathcal{O}(n^3)\)

Submission #74809588 - AtCoder Grand Contest 035

[AGC035F] Two Histograms

有一个 \(n\times m\) 的网格,初始时每个格子都为 \(0\),依次进行以下操作:

  • \(\forall 1\le i\le n\),选择一个整数 \(0\le k_i\le m\),将第 \(i\) 行左边 \(k_i\) 个格子的数加一。
  • \(\forall 1\le j\le m\),选择一个整数 \(0\le l_j\le n\),将第 \(j\) 列上面 \(l_j\) 个格子的数加一。

求两次操作后能得到多少种不同的网格,答案对 \(998244353\) 取模。

\(n,m\le 5\times 10^5\)

神秘。

考虑经典套路将每一种最终的结果唯一对应到一组 \((k,l)\) 上然后对 \((k,l)\) 计数。考虑什么情况下两组不同的 \((k,l)\) 得到的网格是完全相同的,一种比较显然的情况是如果存在 \((i,j)\) 满足 \(k_i=j-1,l_j=i\),那么 \(k_i=j,l_j=i-1\) 且其余 \(k,l\) 不变,这两种情况得到的网格是一样的。

于是我们钦定不能存在 \((i,j)\) 满足 \(k_i=j-1,l_j=i\),并且我们可以证明如果不存在这样的 \((i,j)\),那么两组不同的 \((k,l)\) 得到的网格一定是不同的。

考虑反证法,如果两组不同的 \((k,l)\) 得到的网格是一样的,那么一定存在一个 \(i\) 满足 \(k_i\ne k'_i\)(不然只靠 \(l\) 不相同不能使网格完全一样)。找到最大的这样的 \(i\),不妨设 \(k_i < k'_i\),那么 \((i,k_i+1)\) 这个格子的数一定是 \(1\),即 \(l_{k_i+1}\ge i,l'_{k_i+1} < i\),而因为 \(>i\) 的行的 \(k_j\) 都相同所以 \(l_{k_i+1}\) 最多为 \(i\),此时 \((i,k_i+1)\) 满足 \(l_{k_i+1}=i\)

所以不存在满足 \(k_i=j-1,l_j=i\)\((i,j)\) 是充要条件。考虑计数,钦定有 \(x\) 对这样的 \((i,j)\),要求这 \(x\)\((i,j)\)\(i,j\) 分别互不相同,其余可以任意赋值,答案为:

\[\sum_{i=0}^{min(n,m)}(-1)^i{n\choose i}{m\choose i}i! m^{n-i} n^{m-i} \]

复杂度 \(\mathcal{O}(n)\)

Submission #73778911 - AtCoder Grand Contest 035

AGC034

[AGC034D] Manhattan Max Matching

给定 \(n\) 个三元组 \((rx_i,ry_i,rc_i)\)\(n\) 个三元组 \((bx_i,by_i,bc_i)\),表示二维平面上 \((rx_i,ry_i)\) 处有 \(rc_i\) 个红球,\((bx_i,by_i)\) 处有 \(bc_i\) 个蓝球,保证 \(\sum rc_i = \sum bc_i\),你需要将红球和蓝球两两配对,使得每对两个球的曼哈顿距离之和最大。

\(n\le 1000,rc_i,bc_i\le 10\)

暴力做法为二分图带权匹配,即建立 \(n\) 个左部点和右部点,源点向第 \(i\) 个左部点连流量为 \(rc_i\) 费用为 \(0\) 的边,第 \(i\) 个右部点向汇点流量为 \(bc_i\) 费用为 \(0\) 的边,第 \(i\) 个左部点向第 \(j\) 个右部点连流量为 \(\infty\) 费用为 \(|rx_i-bx_j|+|ry_i-by_j|\) 的边,然后跑最大费用最大流。

考虑优化建图,曼哈顿距离在最大值下有支配性,即可以假设第 \(j\) 个右部点在第 \(i\) 个左部点的左上、右上、左下、右下的哪个方向,将四种答案取 \(\max\) 即为两个点间的曼哈顿距离。于是建立 \(4\) 个虚点表示一组匹配两个点的关系是哪种,不妨设分别为左上、右上、左下、右下。

于是第 \(i\) 个左部点向每个虚点分别连费用为 \(x-y,-x-y,x+y,-x+y\) 的边,每个虚点向第 \(j\) 个右部点连 \(-x+y,x+y,-x-y,x-y\) 的边,这样边数就优化到了 \(\mathcal{O}(n)\) 级别,跑费用流复杂度为 \(\mathcal{O}(n^2f)\)

Submission #74020230 - AtCoder Grand Contest 034

[AGC034E] Complete Compress

给定一棵 \(n\) 个点的树,给定一个长为 \(n\) 的 01 串 \(S\) 表示每个点上是否有棋子,每次操作可以选择两个距离 \(\ge 2\) 的棋子,然后同时向对方的方向移动一条边。求是否能让所有棋子位于一个点,如果能求出最小操作次数。

\(n\le 2000\)

枚举每个棋子最终位于哪个点,以这个点 \(rt\) 为根,那么每次操作一定是让两个不为祖先关系的点同时移向父亲,那么总操作次数就是深度之和除以 \(2\),考虑判断是否有解。

\(f_{u,i}\) 表示子树 \(u\) 能否让所有点距离 \(u\) 的深度之和为 \(i\),可以发现 \(i\) 一定是一个区间内的所有奇数/偶数,于是记录左右端点即可。考虑怎么从 \(u\) 的儿子转移到 \(u\),首先上界显然是所有点都不操作,可以简单计算。而下界一定是所有儿子中最大的 \(l\) 减去其余所有 \(r\),然后将这个值和 \(0\) 取 max,如果此时和上界奇偶不同还要加一。

一直转移到根,看根的下界是否为 \(0\) 即可。复杂度 \(\mathcal{O}(n^2)\)

Submission #74020659 - AtCoder Grand Contest 034

[AGC034F] RNG and XOR

有一个随机数生成器,每次会生成一个 \(0\sim 2^n-1\) 中的数,其中生成 \(i\) 的概率为 \(p_i\)。初始有一个变量 \(X=0\),每次随机生成一个数 \(v\) 并将 \(X\) 异或上 \(v\),对每个 \(i\) 求出 \(X\) 变为 \(i\) 的期望次数。

\(n\le 18\)

\(s\) 变为 \(t\) 的期望次数只和 \(s\oplus t\) 有关,所以求 \(0\) 变为 \(i\) 的期望次数可以转化为求 \(i\) 变为 \(0\) 的期望次数。设 \(f_i\) 表示 \(i\) 变为 \(0\) 的期望次数,那么转移式为 \(f_i=1+\sum\limits_{j=0}^{2^n-1} p_j f_{i\oplus j}\),其中 \(f_0=0\),于是可以用高斯消元做到 \(\mathcal{O}(2^{3n})\) 的复杂度。

转移部分很像异或卷积,于是可以考虑 fwt。考虑 \((p_0,\ldots,p_{2^n-1})\)\((f_0,\ldots,f_{2^n-1})\) 进行异或卷积会得到什么,设得到的数组为 \(g\),则 \(g_i = \sum\limits_{j\oplus k = i}p_jf_k\),所以对于 \(1\le i\le 2^n-1\)\(f_i = 1+g_i\),即 \(g_i = f_i-1\)。而对于 \(g_0\) 我们不知道其具体值,不妨设 \(g_0=f_0-1+C = C-1\),则:

\[(p_0,\ldots,p_{2^n-1}) * (f_0,\ldots,f_{2^n-1}) = (f_0-1+C,f_1-1,f_2-1,\ldots,f_{2^n-1}-1) \]

其中 \(*\) 表示异或卷积,此时将两边同时 fwt,设 \(P,F\) 分别为 \(p,f\) fwt 后的结果,则有 \(P_iF_i = F_i-[i=0]2^n+C\)。因为 \(P_0 = \sum\limits_{i=0}^{2^n-1} p_i = 1\),所以当 \(i=0\) 时有 \(F_0 = F_0-2^n+C\),即 \(C=2^n\)。当 \(i>0\) 时有 \(P_iF_i = F_i+2^n\),即 \(F_i = \frac{2^n}{P_i-1}\)

显然求出 \(F\) 再倒着做一遍 fwt 就能得到 \(f\),先做一遍 fwt 求出 \(P\) 后就能求出所有 \(i>0\)\(F_i\),但此时还有 \(F_0\) 不知道。而因为 \(f_0=0\) 所以 \(\sum\limits_{i=0}^{2^n-1} F_i = 0\),所以有 \(F_0 = -\sum\limits_{i=1}^{2^n-1}F_i\)。总复杂度 \(\mathcal{O}(2^nn)\)

Submission #74032507 - AtCoder Grand Contest 034

AGC033

[AGC033D] Complexity

给定一个 \(n\times m\) 的 01 网格,定义一个网格的复杂度为:

  • 如果网格中的数全为 \(0\) 或全为 \(1\),则复杂度为 \(0\)
  • 否则用一条横着或竖着的线将网格分为两个部分,这种方案的代价为分割出的两个网格复杂度的最大值,则网格的复杂度为所有分割方案代价的最小值。

求网格的复杂度。\(n,m\le 185\)

暴力做法为设 \(f_{l1,r1,l2,r2}\) 表示一个子矩阵的复杂度,时间复杂度为 \(\mathcal{O}(n^5)\)。可以发现一个网格的复杂度是 \(\mathcal{O}(\log (nm))\) 级别的,即整个网格的答案不超过 \(16\),于是可以换维,设 \(f_{l,r,k,v}\) 表示矩阵上下边界分别为 \(l,r\),左边界为 \(k\),复杂度不超过 \(v\) 右边界最大为多少。

首先预处理 \(f_{l,r,k,0}\),固定 \(l,r\) 后双指针扫即可,这部分复杂度 \(\mathcal{O}(n^3)\)。考虑求 \(f_{l,r,k,v}\),如果第一步是竖着切的,那么有 \(f_{l,r,k,v} = f_{l,r,f_{l,r,k,v-1}+1,v-1}\)。如果第一步是横着切的,枚举分割线是在 \(i,i+1\) 之间,有 \(f_{l,r,k,v}\larr \min(f_{l,i,k,v-1},f_{i+1,r,k,v-1})\)。此时复杂度为 \(\mathcal{O}(n^4\log n)\)

复杂度瓶颈在横着切的转移,可以发现 \(f_{l,i,k,v-1}\)\(i\) 递增时单调不升,\(f_{i+1,r,k,v-1}\) 单调不降,于是可以二分求解 \(i\)。但还可以优化,像四边形不等式优化区间 dp 一样,可以发现 \(f_{l,r,k,v}\) 的决策点一定在 \(f_{l,r-1,k,v}\)\(f_{l+1,r,k,v}\) 之间。于是记录每个区间的决策点,然后再在上述两个区间的决策点之间枚举即可,复杂度为 \(\mathcal{O}(n^3\log n)\)

Submission #74195516 - AtCoder Grand Contest 033

[AGC033E] Go around a Circle

一个圆周被 \(n\) 等分,给定一个长为 \(S\) 的 01 串,你需要给每段圆弧赋权值 01,使得:

  • 从圆周上任意一个点出发,都存在一种满足如下条件的方案:
    • 每次走到一个相邻的点,并且第 \(i\) 次走过的圆弧一定为 \(S_i\)

\(2^n\) 种赋值方案中有多少个合法,答案对 \(10^9+7\) 取模。\(n\le 2\times 10^5\)

不妨设 \(S_1=0\),如果 \(S_1=1\) 可以将所有 \(S_i\) 取反。如果 \(S\) 全是 \(0\),那么一种方案合法当且仅当每个点旁边都有至少一段圆弧是 \(0\)。设 \(f_i\) 表示有多少个长为 \(i\) 的 01 串不存在相邻的 \(1\),转移为 \(f_i = f_{i-1}+f_{i-2}\),最终枚举某一段圆弧是 0 还是 1,答案为 \(f_{i-1}+f_{i-3}\)

如果 \(S\) 不全为 \(0\),那么还是要求 \(S\) 不存在相邻的 \(1\),并且可以发现每个 \(0\) 的极长连续段长度一定是奇数,否则可以选择其中一个点作为起点,使得走完第一段 \(0\) 后位于这段 \(0\) 的连续段中间,那么下一步就无法走 \(1\)。而因为每段 \(0\) 长度为奇数,所以每次走完 \(S\) 中的一个 \(0\)\(1\) 连续段后处在的位置是唯一的。

于是对于 \(S\) 中所有不在最后一段的 \(0\) 的极长连续段(因为最后一段走完不用走 \(1\)),记长度最小的为 \(len\),那么要求圆弧中所有 \(0\) 连续段长度不超过 \(len+[len\bmod2=0]\),显然这也是充要条件。记 \(lim = len+[len\bmod 2]\)

考虑计数,对于一个环,将其不断逆时针旋转直到第一段圆弧是 \(1\)。设 \(f_i\) 表示前 \(i\) 段且最后一段为 \(1\) 的的答案,那么 \(f_j\) 能转移到 \(f_i\) 当且仅当 \(i,j\) 同奇偶且 \(i-lim-1\le j < i\),可以用前缀和优化转移。最后枚举最后一个 \(1\) 所在位置 \(i\),要求 \(n-i\) 为奇数且 \(n-i\le lim\),贡献为 \(f_i(n-i+1)\)。复杂度 \(\mathcal{O}(n)\)

Submission #74214865 - AtCoder Grand Contest 033

[AGC033F] Adding Edges

给定一棵 \(n\) 个点的树 \(T\)\(n\) 个点的无向图 \(G\),你可以重复执行以下操作:

  • 选择三个点 \(a,b,c\),使得 \(G\) 中存在边 \(ab,bc\),不存在边 \(ac\),且存在一条 \(T\) 的简单路径同时出现了 \(a,b,c\),添加边 \(bc\)

求不断操作后最终 \(G\) 有多少条边。

\(n,m\le 2000\)

考虑在不改变答案的情况下对 \(G\) 做一些变换,一条 \(G\) 中的边可以通过加边得到那么可以删去。如果 \(T\) 的一条路径上依次出现了 \(a,b,c\),且 \(G\) 中有边 \(ac,bc\),那么可以删去边 \(ac\),加入边 \(ab\)。这样子不断操作后,最终是否有边 \(uv\) 就是看 \(T\)\(u\) 为根时能否只走 \(G\) 中的祖孙边从 \(u\)\(v\),答案是好计算的。

考虑怎么得到最终的 \(G\),可以不断加边并实时维护当前的 \(G\)。设 \(f_{x,y}\) 表示以 \(x\) 为根,与 \(x\) 有连边离 \(y\) 最近的祖先的是哪个点。设当前要加入边 \((x,y)\),分以下几种情况:

  • 如果 \(f_{x,y} = y\),说明已经存在边 \((x,y)\),不用管。
  • 如果 \(f_{x,y}\ne 0\),则改为加入边 \((f_{x,y},y)\)。同理如果 \(f_{y,x}\ne 0\),则改为加入边 \((f_{y,x},x)\)
  • 如果 \(f_{x,y} = f_{y,x} = 0\),则加入边 \((x,y)\),接下来处理 \(f_{x,i}\)\(f_{y,i}\) 的改变。处理 \(f_{x,i}\) 的改变时,让 \(T\)\(x\) 为根然后从 \(y\) 开始 dfs,如果遇到一个 \(f_{x,i}\ne 0\) 的点 \(i\) 那么一定是有边 \((x,i)\),此时删去边 \((x,i)\) 并加入边 \((y,i)\) 并结束 dfs,否则将路上经过的所有 \(i\)\(f_{x,i}\) 设为 \(y\)

为什么遇到 \(f_{x,i}\ne 0\) 直接结束是对的?因为要删去 \((x,i)\) 所以理论上我们应该将 \(i\) 子树内的 \(f_{x,i}\) 设为 \(y\) 而不是 \(i\)。但实际上我们只会在加入 \((x,j)\) 的边时用到 \(f_{x,i}\),其中 \(j\)\(i\) 子树内的点,而因为存在边 \((x,y),(y,i)\) 所以实际上是加边 \((i,j)\),用 \(f_{x,i} = i\) 也是对的,相当于少转化一步。

可以发现每个 \(f_{i,j}\) 最多一次被设为非 \(0\),每条边最多被加一次,所以复杂度为 \(\mathcal{O}((n+m)n)\)

AGC032

[AGC032D] Rotation Sort

给定一个 \(1\sim n\) 的排列 \(p\),你可以进行以下两种操作:

  • 选择 \(1\le l < r\le n\),将 \(p_l,\ldots,p_r\) 向左循环移位一次,代价为 \(A\)
  • 选择 \(1\le l < r\le n\),将 \(p_l,\ldots,p_r\) 向右循环移位一次,代价为 \(B\)

求将 \(p\) 排序的最小代价。\(n\le 5000\)

操作一可以看成选择一个 \(a_i\) 将其放到右边的一个位置,操作二可以看作放到左边的一个位置。显然一个数不会操作两次及以上,因为一次到位一定更优。于是枚举每个 \(p_i\) 是否向左移动过、向右移动过或者没被操作过,考虑如何判断一种方案是否合法。

整个 \(p\) 是升序的当且仅当每个 \(p_i\) 前面没有比它大的数,那么每个 \(p_i\) 都要求要么 \(p_i\) 向左移动过,要么 \(p_i\) 前面不存在没向右移动过且比 \(p_i\) 大的数,容易证明这是充要条件。设 \(f_{i,j}\) 表示前 \(i\) 个数,没有向右移动过的数中最大的数是 \(j\),考虑 \(f_{i-1,j}\) 如何转移:

  • 如果 \(p_i\) 选择不动,则要求 \(p_i>j\)\(f_{i,p_i}\larr f_{i-1,j}\)
  • 如果 \(p_i\) 选择向右移动,则要求 \(p_i>j\)\(f_{i,j}\larr f_{i-1,j}+a\)
  • 如果 \(p_i\) 选择向左移动,则没有要求,\(f_{i,\max(j,p_i)}\larr f_{i-1,j}+b\)

最后答案为 \(\max f_{n,j}\)。复杂度 \(\mathcal{O}(n^2)\)

Submission #74448418 - AtCoder Grand Contest 032

[AGC032E] Modulo Pairing

给定 \(n,m\)\(2n\)\([0,m)\) 间的整数 \(a_1,\ldots,a_{2n}\),将这些整数两两配对,一对 \((x,y)\) 的代价为 \((x+y)\bmod m\),求所有配对方案中每对代价最大值最小能是多少。

\(n\le 10^5\)

首先将 \(a\) 排序,将配对中 \(x+y < m\) 的染为蓝色,\(x+y\ge m\) 的染为红色。可以发现匹配方案一定如下:

可以使用调整法来证明,如下图:

可以发现红蓝的分界线越往左越好,但是如果太左边那么红色部分就不能保证全为 \(x+y\ge m\),于是二分这个端点即可。复杂度为 \(\mathcal{O}(n\log n)\)。精细实现可以做到 \(\mathcal{O}(n)\)

Submission #74448731 - AtCoder Grand Contest 032

[AGC032F] One Third

有一个面积为 \(1\) 的圆形披萨,一个人在上面随机切了 \(n\) 刀,每次切割是从圆心到圆上随机一个点。现在你希望选出一段连续的披萨使得面积和 \(x\) 尽可能接近 \(\frac 1 3\),求 \(|x-\frac 1 3|\) 最小值的期望值。

\(n\le 10^6\)

神仙题。

首先需要知道一个定理:在 \([0,1]\) 上随机取 \(n-1\) 个点,形成的 \(n\) 条线段中最短的长度期望为 \(\frac 1 {n^2}\)。证明考虑枚举 \(x\) 表示所有线段长度 \(\ge x\),概率为 \((1-nx)^n\),于是答案为:

\[\begin{aligned} \mathbb E (L_{min}) &= \int_0^{\frac 1 n} (1-nx)^n \mathrm dx \\ &= \int_0^{\frac 1 n} (1-nx)^{n-1} \mathrm d(1-nx) \frac{\mathrm dx}{\mathrm d(1-nx)} \\ &= -\frac 1 n \times \frac 1 n\times (1-nx)^n\bigg |_0^{\frac 1 n} \\ &= \frac 1 {n^2} \end{aligned} \]

接下来考虑次长线段的期望值,将所有线段长度减去最短线段长度后是一个 \(n-1\) 条线段的子问题,于是次长线段期望长度为 \(\mathbb E (L_{min})+\mathbb E(\frac{1-L_{min}}{(n-1)^2}) = \frac 1 n(\frac 1 n+\frac{1}{n-1})\)。同理可得第 \(k\) 短的线段期望长度为 \(\frac 1 n(\frac 1 n+\frac 1 {n-1}+\ldots+\frac{1}{n-k+1})\)

接下来是一个非常厉害的转化:将切的 \(n\) 个半径染成红色,然后将所有半径顺时针旋转 \(\frac 2 3\pi\) 并染为蓝色,再将所有半径顺时针旋转 \(\frac 2 3\pi\) 并染为绿色,即现在圆上有 \(3n\) 条三种颜色的半径,那么答案为任意两条不同颜色的半径的角度差的最小值。证明就是对于任意两个一开始的角度 \(x,y\),一定存在一种旋转方案使得它们两个的角度差就是原来的角度差到 \(\frac 2 3\pi\) 的距离。因为答案一定 \(<\frac 2 3\pi\),所以取同一个半径的两种颜色一定不优。

可以发现答案一定是两个相邻的不同色的半径,不然不优。我们任意找一个半径,只保留这个半径顺时针 \(\frac 2 3\pi\) 范围的所有半径。对于两个原来的角度 \(x,y\),考虑取到它们答案的旋转方案中,要么存在一种是两个角度都在上述范围内,要么是一个角度在另一个不在,因为 \(0,\frac 2 3\pi\) 处存在半径所以这种情况一定不优。

现在问题变为了在 \([0,\frac 1 3]\) 中任取 \(n-1\) 个点,并给每个点随机染红蓝绿中的一种颜色,且 \(0,\frac 1 3\) 处各存在一个红色、蓝色的点,求相邻两个不同色的点的最小距离期望。枚举这段最小距离是所有线段中第 \(i\) 小的,那么前 \(i-1\) 段要求两个端点同色,第 \(i\) 段要求两个端点不同色,概率为 \(\frac 1 {3^{i-1}}-[i\ne n]\frac 1 {3^i}\),因为首尾两个点颜色不同所以不可能 \(n\) 段颜色都相同。于是答案为:

\[\begin{aligned} &\frac 1 3\sum_{i=1}^n \frac 1 n\times(\frac 1 {3^{i-1}}-[i\ne n]\frac 1 {3^i})\times \sum_{j=1}^i\frac 1 {n-j+1} \\ =& \frac 1 {3n}\sum_{j=1}^n\frac 1 {n-j+1}\sum_{i=j}^n (\frac 1 {3^{i-1}}-[i\ne n]\frac 1 {3^i}) \\ =& \frac 1 n\sum_{j=1}^n \frac 1 {3^j(n-j+1)} \end{aligned} \]

复杂度 \(\mathcal{O}(n)\).

Submission #74745511 - AtCoder Grand Contest 032

AGC031

[AGC031E] Snuke the Phantom Thief

在二维平面上,有 \(n\) 个珠宝,第 \(i\) 个在 \((x_i,y_i)\) 位置处,价值为 \(v_i\)。现在你可以偷走一些珠宝,有 \(m\) 条限制,每条限制为以下 \(4\) 种之一:

  • 横坐标小于等于 \(a_i\) 的珠宝最多偷 \(b_i\) 颗。
  • 横坐标大于等于 \(a_i\) 的珠宝最多偷 \(b_i\) 颗。
  • 纵坐标小于等于 \(a_i\) 的珠宝最多偷 \(b_i\) 颗。
  • 纵坐标大于等于 \(a_i\) 的珠宝最多偷 \(b_i\) 颗。

求在满足这些限制条件的情况下,偷的珠宝的最大价值和是多少。

\(n\le 80,m\le 320,x_i,y_i\le 100,0\le v_i\le 10^{15}\)

横坐标小于等于 \(a_i\) 的珠宝最多偷 \(b_i\) 颗,就相当于在按横坐标排序后,编号 \(> b_i\) 的珠宝横坐标都要 \(> a_i\)。其余三个限制同理可以转化。

因为最终偷的珠宝个数不确定不太好做,我们可以枚举这个珠宝数 \(x\),然后可以根据这些限制确定出按横坐标排序后,每个珠宝的横坐标的范围是多少,纵坐标同理,相当于把所有限制的区间取交。那么对于一个珠宝 \((x_i,y_i,v_i)\),我们可以根据它的 \((x_i,y_i)\) 来确定它能放到横坐标的哪个区间和纵坐标的哪个区间,于是就可以考虑费用流。

处理出横坐标的 \(x\) 个区间限制和纵坐标的 \(x\) 个区间限制。源点向所有横坐标区间连 \((1,0)\) 的边,所有纵坐标区间向汇点连 \((1,0)\) 的边。然后将所有珠宝拆成左右两个点,中间连 \((1,v_i)\) 的边。然后如果一个珠宝满足某个横坐标区间的限制,那么这个横坐标区间向珠宝左边的点连边,纵坐标同理。然后跑最大费用最大流即可,如果一组匹配的横坐标或纵坐标并不是有序的,显然交换成有序的依然合法。

[AGC031F] Walk on Graph

给定一张 \(n\) 个点 \(m\) 条边的连通无向图,每条边有边权 \(w_i\),给定一个奇数 \(p\)。你需要回答 \(q\) 次询问:

  • 每次询问给定 \(s,t,r\),判断是否存在一条从 \(s\)\(t\) 的路径满足路径长度模 \(p\)\(r\),其中路径长度定义为第 \(i\) 条边边权乘 \(2^i\) 之和。路径不一定是简单路径。

\(n,m,q\le 5\times 10^4,p\le 10^6\)

神仙题。

首先将询问改为从 \(t\)\(s\),设当前路径长度为 \(x\),那么经过一条边权为 \(w\) 的边后会变为 \((2x+w)\bmod p\)。于是可以建出 \(n\times p\) 个点,对于一条边 \((u,v,w)\) 连边 \((u,i)\to (v,2i+w)\)(第二维默认在 \(\bmod p\) 意义下运算),询问就是判断 \((t,0)\) 能否走到 \((s,r)\),这个做法复杂度为 \(\mathcal{O}(m\times p)\)

可以发现每条有向边都可以改为无向边,因为 \(p\) 是奇数所以 \(i\to (2i+w)\bmod p\) 一定是一个双射,再走回来 \(i\to (4i+3w)\bmod p\) 也是一个双射,即从 \((u,i)\) 一直走 \((u,v,w)\) 这条边一定会回来,所以所有有向边都可以改为无向边,这样就可以用并查集来维护。

但这样点数还是太多了,考虑如果存在两条边 \((u,p,a),(u,q,b)\),那么从 \(u\)\(p\) 再到 \(u\) 可得 \((u,i)\) 能到 \((u,4i+3a)\),同理能到 \((u,4i+3b)\),设 \(j = 4i+3a\) 可得 \((u,j)\) 能到 \((u,j+3(b-a))\)。设 \(g_u\) 表示 \(u\) 所有邻边边权差的 \(\gcd\)\(3\),那么 \((u,j)\) 能到 \((u,j+g_u)\),因为是在模意义下所以可以令 \(g_u\larr \gcd(p,g_u)\)

求出所有 \(g_u\),如果有边 \((u,v,w)\),那么可以让 \(g_v\larr \gcd(g_v,2g_u)\),因为 \(p\) 是奇数所以 \(g_u\) 是奇数所以 \(\times 2\) 没用,即 \(g_v\larr \gcd(g_v,2g_u)\)。因为整个图连通所以一直做下去所有 \(g_u\) 都会等于 \(\gcd\limits_{i=1}^n g_i\),而这个值也等于任意两个边权之差的 \(\gcd\)\(3\) 后与 \(p\)\(\gcd\)。设 \(g = \gcd\limits_{i=2}^m (g_i-g_1)\),即任意两个边权之差的 \(\gcd\),那么可以将 \(p\) 改为 \(\gcd(p,3g)\),并将所有边权 \(\bmod p\)

考虑如果所有 \(w\) 都一样怎么做,我们可以用 \((u,i-w)\) 来替代 \((u,i)\),这样子原来是 \((u,i-w)\to (v,2i-w)\),现在是 \((u,i)\to (v,2i)\),也就是说所有边权变为了 \(0\),问题变为从 \((t,w)\)\((s,r+w)\)

因为我们只能用 \(\times 2\),所以 \((u,i)\) 能到的只有 \((x,2^t i)\),而一个点走一条边再回来可以让长度 \(\times 4\),所以只用关心 \(t\le 1\),于是一个点只有 \((u,i),(u,2i)\) 两种状态。现在状态数只有 \(2n\) 个,可以直接用并查集来做。

考虑原问题,因为任意两个边权之差的 \(\gcd\)\(g\),而 \(p\le 3g\),所以每条边权都可以表示为 \(kg+d\) 的形式,其中 \(0\le k\le 2,0\le d < g\),像上面一样用 \((u,i-d)\) 来替代 \((u,i)\),这样每条边权变为了 \(kg\),于是 \((u,i)\) 能到的只有 \((u,2^t i+lg)\)

首先有 \(k\le 2\),同理,\((u,i+lg)\) 走一条边再走回来会得到 \((u,4i+4lg+3kg)\)\((u,4i+lg)\),所以我们只用关心 \(l\le 1\)。于是每个点最多有 \(6\) 种状态,总状态数就是 \(\mathcal{O}(n)\) 的,还是直接用并查集即可。一开始预处理每个 \(i\) 不断 \(\times 4\) 能到哪些数,即分成若干个等价类。询问时枚举 \((t,d)\) 走到了 \((u,2^t d+lg)\) 这个状态,看 \(2^td+lg\)\(r+g\) 是否在同一个等价类。复杂度为 \(\mathcal{O}(p+m+q)\)

Submission #74562529 - AtCoder Grand Contest 031

AGC030

[AGC030E] Less than 3

给定两个长为 \(n\) 的 01 串 \(s,t\),保证 \(s,t\) 中不会出现连续三个相同的数。每次操子可以将 \(s\) 中的某一位取反,要求每次操作后依然要满足不会出现连续三个相同的数。求将 \(s\) 变为 \(t\) 的最小操作次数。

\(n\le 5000\)

\(s'_i = s_i\oplus s_{i-1}\),其中 \(s_1' = s_1\)\(t'\) 同理,显然如果 \(s',t'\) 相同那么 \(s,t\) 就相同,于是在 \(s',t'\) 上考虑。原来限制为不能出现三个连续相同的数,在 \(s'\) 中就是除了 \(s'_1,s'_2\) 其余位置不能出现 \(00\)。每次操作是相邻两个数同时取反,而因为除了开头不能出现 \(00\),所以两个数同时取反只能是 \(01\)\(10\) 间转化。

现在问题变为了给定两个长为 \(n\) 的 01 串 \(a,b\),每次可以交换 \(a\) 中两个数,保证 \(a\) 除了开头没有 \(00\),特殊地,每次操作还可以将开头的 \(00\) 变为 \(11\)\(11\) 变为 \(00\),也可以只将最后一位取反,求 \(a\) 变为 \(b\) 的最小操作次数。

可以发现一段前缀和一段后缀可能会涉及到特殊的操作,中间段只做了交换相邻数的操作。考虑如果没有后面两种特殊操作答案是什么,设 \((p_1,\ldots,p_k),(q_1,\ldots,q_m)\) 分别表示 \(a,b\) 从左往右第 \(i\)\(0\) 的位置,则要求 \(k=m\),答案为 \(\sum\limits_{i=1}^k |p_i-q_i|\)。如果加上可以取反最后一位的操作,相当于将两个数组少的那个后面用 \(n\) 补齐,然后答案同上,注意要额外加上 \(|k-m|\)

接下来再加上开头的特殊操作,可以发现 \(a\) 不会同时出现将 \(00\) 变为 \(11\) 或将 \(11\) 变为 \(00\) 两种操作,不妨设只出现了将 \(11\) 变为了 \(00\) 的操作,做一遍从 \(a\)\(b\) 再做一遍从 \(b\)\(a\) 即可。枚举这种操作一共出现了 \(x\) 次,那么 \(b\) 中前 \(2x\)\(0\) 就会由这些操作得到,次数为 \(x+\sum\limits_{i=1}^x (q_{2i-1}+q_{2i}-3)\),其余部分算法和上面相同。总复杂度为 \(\mathcal{O}(n^2)\)

Submission #74581300 - AtCoder Grand Contest 030

[AGC030F] Permutation and Minimum

有一个 \(1\sim 2n\) 的排列 \(a\),构造一个长为 \(n\) 的数组 \(b\)\(b_i = \min(a_{2i-1},a_{2i})\)。现在给定 \(a\) 中的一些数,求所有满足条件的排列 \(a\) 能生成多少不同的 \(b\)

答案对 \(10^9+7\) 取模。\(n\le 300\)

对于每个 \(1\le i\le n\)\(a_{2i-1},a_{2i}\) 有三种情况,分别是两个都确定了,确定了一个和都没确定,如果两个数都确定了可以直接忽略,设三种情况的数分别为一类、二类、三类。设有 \(c\) 组三类数,可以不考虑这些 \(b_i\) 间的顺序,最后将答案乘上 \(c!\)

忽略一类数,现在要将剩下的数两两配对,要求二类数间不能配对。于是我们只关心每组配对中小的那个数构成的集合,或者一组配对中大的数是二类数那么还关心这个二元组。

\(f_{i,j,k}\) 表示考虑了 \(i\sim 2n\) 中的数,有 \(j\) 个三类数没有匹配,有 \(k\) 个二类数没有匹配,考虑 \(f_{i+1,j,k}\) 如何转移到 \(f_i\)

  • 如果 \(i\) 是一类数则直接忽略。
  • 如果 \(i\) 是二类数,它可以和一个未匹配的三类数进行匹配,即 \(f_{i,j-1,k}\larr f_{i+1,j,k}\),或者和之后的数匹配,即 \(f_{i,j,k+1}\larr f_{i+1,j,k}\)
  • 如果 \(i\) 是三类数,它可以和一个未匹配的三类数进行匹配,即 \(f_{i,j-1,k}\larr f_{i+1,j,k}\),或和未匹配的二类数匹配,而因为二类数间是关心顺序的,即 \(f_{i,j,k-1}\larr f_{i+1,j,k}\times k\),或和之后的数匹配,即 \(f_{i,j+1,k}\larr f_{i+1,j,k}\)

最终答案为 \(f_{1,0,0}\times c!\)。复杂度 \(\mathcal{O}(n^3)\)

posted @ 2026-04-07 21:04  max0810  阅读(13)  评论(0)    收藏  举报