AGC 做题合集 #8

代码啥的,可以看之前文章里面的网址,不想再打一遍了……

  1. "AGC019F Yes or No"[1]
  2. "AGC044D Guess the Password"[2]
  3. "AGC026E Synchronized Subsequence"[3]
  4. "AGC037E Reversing and Concatenating"[4]
  5. "AGC017E Jigsaw"[5]
  6. "AGC020E Encoding Subsets"[6]
  7. "AGC011E Increasing Numbers"[7]
  8. "AGC033D Complexity"[8]
  9. "AGC009E Eternal Average"[9]
  10. "AGC021C Tiling"[10]

  


  1. AGC019F Yes or No

    \(N+M\) 个问题,其中有 \(N\) 个问题的答案是 YES\(M\) 个问题的答案是 NO。当你回答一个问题之后,会知道这个问题的答案,求最优策略下期望对多少。

    答案对 \(998244353\) 取模。

    \(N, M \le 5\times 10^5\)


    首先有一个 \(\mathcal O(n^2)\) 的 DP,考虑设答案为 \(f(n, m)\),那么我们的策略是猜 \(n, m\) 更大的对应的选项。

    于是:

    \[f(n, m) = \frac{n}{n+m}f_{n - 1, m} + \frac{m}{n + m}f_{n, m - 1} + \frac{\max(n, m)}{n + m} \]

    把 DP 转到网格图上面,横坐标是 \(n\),纵坐标是 \(m\),这个就是网格上面不断走路的问题。

    考虑 \(y = x\) 这条线,比较特殊,同时我们考虑答案的线的状况,也就是我们从 \((n, m)\) 走到 \((0, 0)\) 的过程,而每一次我们选择的答案都是靠近 \(y = x\) 这条线的方向,通过手玩可以发现,我们无论如何,都会有 \(\max\{n, m\}\) 的收益,而唯一不确定的就是在 \(y = x\) 的时候我们的答案是蒙的,于是答案就是 \(\max\{n, m\}\) + 所有路径和 \(y = x\) 相交次数的期望 \(\times \frac{1}{2}\)

    后面这个是好做的,直接枚举在那个节点贡献,就是组合数了。 ↩︎

  2. AGC044D Guess the Password

    这是交互题。

    有一个密码 \(S\),字符集为 \(\{a, b, \dots, z, A, B, \dots, Z, 0, 1, \dots, 9\}\),你不知道,长度都不知道(\(\le L\))。

    每次,你可以猜一个密码 \(T\),交互器会告诉你 \(S\)\(T\) 的最短编辑距离(每次可以删除、添加、替换一个字符,最少步数使得 \(S = T\)),在 \(Q\) 次询问后给出密码。

    \(L = 128, Q = 850\)


    比较 easy 的 *3100,没有太多拐弯抹角。

    长度都不知道就比较 **,考虑先解决长度问题。

    我们直接丢一个长度为 \(L\) 的全 a 串,然后就知道 a 的个数了!类似的,直接用 \(|\Sigma|\) 的次数不仅问出来长度,甚至问出每个字符出现次数了!

    问出了长度,我们就可以更进一步了,接下来的策略有几种(我想的):

    • 考虑增量构造,每次插入一个字符,然后通过某种奇怪的方式确定这个字符位置。
    • 考虑增量构造,每次确定下一个字符。
    • 考虑将字符集从 \(\{a\}\) 不断拓展到 \(\{a, b\}\),直到到了 \(\Sigma\)

    经过推断后,可以发现最后一种方案比较有前途。

    考虑 \(\Sigma = \{a, b\}\) 怎么搞,现在我们有一堆 a 和一堆 b,我们不断确定 a 中间空隙的 b 的个数,一个比较重要的性质就是如果在 \(T\) 中插入了一个对的字符(比如原来 \(T\)\(S\) 的子序列,插入后还是 \(S\) 的子序列),那么编辑距离会减少。为此,我们可以类似归并排序一样,不断试着把空隙填满,如果填满了,就到下一个空隙中间。可以发现次数是 \(\mathcal O(cnt_a + cnt_b)\) 的。

    最后一步,我们知道启发式合并,它的本质是小的碰到大的,这个代价是小的大小,而这个题,我们可以每次选择 \(cnt\) 最小的两个串合并,于是次数就是 \(\mathcal O(L\log L)\) 了! ↩︎

  3. AGC026E Synchronized Subsequence

    有一个长度为 \(2 N\) 的仅由字符 \(\mathtt{a}, \mathtt{b}\) 构成的字符串,且 \(\mathtt{a}\) 的个数恰好等于 \(\mathtt{b}\) 的个数,都出现了 \(N\) 次。你需要保留一些字符,剩下的字符删掉。对于一个 \(i\),你可以保留从左往右数的第 \(i\)\(\mathtt{a}\) 和第 \(i\)\(\mathtt{b}\)。注意,对于这两个字符,只能同时保留或同时删掉,不能只保留其中一个。请你求出能得到的字典序最大的串。

    \(1 \le N \le 3 \times {10}^3\)


    猜结论去了,人麻了。

    考虑 DP,记 \(f(i)\) 表示目前考虑了 \(\ge i\) 的所有 ab 对的答案。

    对于第 \(i\)ab,我们分类考虑保留这一对 ab 的最大答案,最后和 \(f(i + 1)\)\(\max\) 即可:

    • a 先出现,如果要保留这一对 ab,那么所有在 ab 间的 a 不能保留,因为比较拉跨,而对于 b 如果保留了,还不如删了这一对,于是 ab 间都不能保留,记 b 后面第一对为 \(t\),那么 \(f(i) = \texttt{"ab"} + f(t)\)
    • b 先出现,这个是比较优秀的,而这个 a 是比较劣质的,于是我们要在这个 ab 之间尽量填满 b,直接取出中间所有 b \(\ge i\) 的对,取出后,我们发现,我们会触发连锁反应,于是一直加加加,直到加完了位置,然后继承后面答案。

    答案就是 \(f(1)\)↩︎

  4. AGC037E Reversing and Concatenating

    给定一个长度为 \(n\) 的只包含小写字母的字符串 \(s\) 和正整数 \(k\),求进行 \(k\) 次如下操作后:

    \(s\)\(s\) 的翻转拼接(\(s\) 在前)得到 \(t\),从 \(t\) 中截取长度为 \(n\) 的子串作为新的 \(s\)

    字典序最小的 \(s\)

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


    简单题,只要几个推论即可。

    Lemma 1

    有效的 \(K\) 不是很大,最多 \(\mathcal O(\log n)\)

    考虑取出最小位置 \(p\),第一次,我们可以让 \(p\) 所在的地方为串的末尾,接下来,每一次,我们复制后,都能让 \(p\) 的个数 \(\times 2\),在 \(\mathcal O(\log n)\) 的时间内,直接全部是 \(p\) 了。

    Lemma 2

    在前 \(K-1\) 次操作中,我们选择的 \(T\) 满足 \(\overline{T}\)\(T\) 反转后的字符串) 字典序最小。

    最后一次暴力贪心即可。

    为什么呢?首先,我们在前 \(K-1\) 次操作中,一定是优先让末尾的最小的字符数目尽可能多,其次,是为了让之后的选择更优,结合手玩可以发现,我们只要选择 \(\overline{T}\) 最小的即可。


    综上所述,直接暴力即可,复杂度 \(\mathcal O(n^2\log n)\)↩︎

  5. AGC017E Jigsaw

    题面还是看原题面吧,不太好描述。


    rnm,不会处理连成环的情况/kk。

    首先,对于 \(i \to j\) 这种连接方式合法当且仅当 \(B_i = C_j, D_i = 0\) 或者 \(D_i = A_j, C_j = 0\),这个启示我们建图,对于一个拼图,如果左边的 \(C_i = 0\) 那么代表值就是 \(A_i\),否则就是 \(C_i+H\),如果右边的 \(D_i=0\) 那么代表值就是 \(B_i+H\),否则就是 \(D_i\),然后左边的代表值向右边的代表值连一条边,容易发现,我们拼起来的方案就对应这若干条路径,每条从 \(i \le H\) 的点出发,不重复的经过每条边,最后在 \(j > H\) 的点结束。

    我们可以根据度数判断是否有解,对于 \(i \le H\) 的点,一定是出度 \(\ge\) 入度的,对于 \(i > H\) 的点,一定是出度 \(\le\) 入度的。

    最后一个问题就是会出现连成一个环的情况,这个可以判断一下对于一个弱连通的图是否是 "卡死" 的,即所有点的入度 = 出度,如果卡死了,那么就会形成环,否则不会。 ↩︎

  6. AGC020E Encoding Subsets

    我们定义一个 01 串的压缩是满足如下方式的字符串变化过程:

    • \(0\rightarrow 0,1\rightarrow 1\)
    • 如果 \(A\rightarrow P,B\rightarrow Q\) 合法,那么 \(A+B\rightarrow P+Q\) 也合法(其中 \(+\) 代表字符串拼接)
    • 如果 \(S=\underbrace{A+A+\cdots+A}_{n\text{个}(n\ge 2)}\),那么 \(S\rightarrow(A\times n)\) 也合法(其中 (, ), × 为字符,\(n\) 为数字,算作一个字符,即使其中有 \(0/1\)

    我们同时定义 \(01\)\(B\)\(A\) 的子集当且仅当:

    • \(|A|=|B|\)
    • \(\forall B_i=1,A_i=1\)

    现在给你一个 \(01\)\(S\),问它所有的子集的合法变化结果数的总和为多少。

    答案对 \(998244353\) 取模。\(|S| \le 100\)


    不懂诶,这种题简直就是写出即胜利,为什么会是 *2900,为什么 luogu 对于 *3400 都要评蓝了而这个题还是黑,难道仅仅是题目标号带了 E?我不理解,但大受震撼。

    \(|S| \le 100\),这种数据范围告诉我们不要高估自己算法的复杂度。

    于是可以考虑怎么优雅地写暴力。

    我们记 \(f(s)\) 表示 \(s\) 字符串的答案,\(g(s)\) 表示 \(s\) 字符串必须表示为 \((t\times k)\) 的形式(其中 \(k >1\))的答案。

    对于 \(g(s)\) 的转移,直接枚举循环节长度 \(len\),然后所有段合一起(对应位置取 \(\min\)),递归成 \(f(t)\) 的问题。

    对于 \(f(s)\) 的转移,我们直接枚举 \(i, j\) 表示 \(s[0: i - 1]\) 是不能整花活(不能带有括号,显然方案是 \(2^t\),其中 \(t\)\(s[0 : i - 1]\)\(1\) 的个数)的,\(s[i : j]\) 是必须为 \(g\) 类型方案的,\(s[j + 1:]\) 是任意的,然后直接乘起来。当然,还要加上 \(s\) 压根不整花活的方案,\(2^t\)

    调完样例后发现跑得速度很快,手动测一测 \(n = 100\),发现能过?

    然后就切了此题。此题唯一难点在于敢于写出暴力 DP。

    因为没有看题解,所以解法有点奇怪,似乎有 \(\infty\) 倍常数,于是抢到了 Atcoder 的第 \(6\) 裂解。


    刚看了一下大家的做法,顺便写一写,不过思路是差不多的,但是设计的状态比较巧妙。

    \(f(s)\) 表示 \(s\) 的答案,\(g(s)\) 必须表示为单一字符或者由括号括起来的形式。

    这样转移的时候就只要枚举一个分界点,并且常数减小了一些。 ↩︎

  7. AGC011E Increasing Numbers

    我们说一个数是“递增的”,当且仅当对于它的任意相邻的两位都有左边小于等于右边。
    \(1558\), \(11\), \(3\) 是递增的,\(20170312\)\(19260817\) 就不是。
    现在给你一个数 \(n\),问最少可以被表示成几个递增的数之和。
    比如 \(80 = 56 + 24\)\(2017 = 1349 + 668\), \(2019 = 1669 + 237 + 113\)

    \(1 ≤ n ≤ 10^{500000}\)


    做出铜牌题好开心!不过话说回来,铜牌题就这?

    对于递增的数,显然类似于洛谷 P2481 [SDOI2010]代码拍卖会,将其拆成若干个 \(000\dots0111\dots1\)

    接下来就比较 easy 了,从高到低考虑,显然会被低位的进位所影响,于是果断从低位到高位考虑。

    假设我们现在有 \(t (t \bmod 10 = n \bmod 10)\) 个这种 \(111\dots1\) 的数字(并且,我们目前考虑到了第 \(i\) 位,这些数字后面的 \(i - 1\) 位都是 \(1\),前面的还没有确定),并且我们上一位给了我们进了 \(v\) 次位,如果我们这 \(t\) 个数这一位还是全部设为 \(1\),那么这一位的数就是 \(t+ v \bmod 10\),如果和目标不同,我们就只能通过让 \(x\) 个数这一位为 \(0\) 解决,如果最小的 \(x\)\(> t\),那么我们就寄了,因为我们没有办法进行调整,否则我们直接让 \(t\) 减去最小的 \(x\)。为什么一定是最小的呢,因为这样我们会在后面有更多的自由度。

    最后不断操作,如果到了第 \(0\) 位,考虑进位了 \(0\) 的数,如果是 \(0\),那么就是一个合法的方案了,否则就意味着我们的这种 \(000\dots0111\dots1\) 数过多了,可以考虑减少一下(我声称这是可以的,可以通过调整法,在 1 位置大量减少这种数,使得进到 0 的数为 0)

    注意上面的证明不是非常严谨,但是作为做题人,只要到这一步就差不多了,在本机 Rand 几个数可以发现,一定存在一个分解点 \(lim\),满足有 \(lim\) 个这种数的情况下就是 OK 的,在 \(<lim\) 个数的情况下就会寄,多了就只会出现进位到 \(0\) 的数过多的情况。

    于是这个是有单调性的,可以直接二分答案。复杂度 \(\mathcal O(\log_{10} n \log_{2} {\log_{10} n})\)这就是传说中的复杂度带个 \(\log\log\) 吗。 ↩︎

  8. AGC033D Complexity

    给定一个 \(N\)\(M\) 列的字符矩阵。

    我们定义一个字符矩阵的凌乱度为:

    • 若这个字符矩阵中所有字符都相同,则凌乱度为 \(0\)
    • 否则,则考虑所有的沿水平或者竖直方向的直线,将字符矩阵分成两个不为空的部分,设两个部分的凌乱度分别为 \(a\)\(b\),则整个字符矩阵的凌乱度为 \(\max(a,b)+1\) 的最小值。

    请你求出,给出的字符矩阵的凌乱度是多少。

    \(1 \leq N, M \leq 185\)


    以前的讲课题,知道大概思路,但是没有落实。今天 VP 的是否突然发现有这个题,于是编了编细节,然后写了写。

    首先,我们有一个朴素的状态,\(f(a, b, c, d)\) 表示 \((a,b)\) 为左上角,\((c,d)\) 为右上角的凌乱度,而这个状态就是 \(\mathcal O(n^2m^2)\) 的,而转移还有一个 \(n+m\) 的复杂度,肯定寄了。

    但是我们发现,这个题目的答案是比较小的(\(\mathcal O(\log n + \log m)\)),于是可以考虑将状态与答案互换,设 \(f(i, j, k, d)\) 表示从 \(i\) 行到 \(j\) 行从 \(k\) 列开始的凌乱度为 \(d\) 的最右边列是什么,而 \(g(i, j, k, d)\) 表示从 \(i\) 列到 \(j\) 列从 \(k\) 行开始的凌乱度为 \(d\) 的最下的行是什么。

    \(f\) 转移为例,枚举划分方式,根据列切,那么就是 \(f(i, j, f(i, j, k, d - 1) + 1, d - 1)\) 了,如果按照行切,那么就要根据 \(g\) 来转移,也就是找到最大的 \(p\) 满足 \(g(k, p, g(k, p, i, d - 1) + 1, d - 1) \ge j\) 了,而在 \(i,j\) 固定而 \(k\) 递增的时候 \(p\) 是又单调性的,可以直接双指针求出。

    复杂度 \(\mathcal O(n^2m (\log n + \log m))\)↩︎

  9. AGC009E Eternal Average

    黑板上有 \(n\) 个 0 和 \(m\) 个 1,我们每次选择 \(k\) 个数字将其擦除,然后把它们的平均数写上去,这样一直操作直到只剩下一个数字,问剩下的这个数字有多少种不同的情况。

    答案对 \(10^9+7\) 取模

    \(1 \leq n,m \leq 2000,2 \leq k \leq 2000\)

    保证 \(n+m-1\) 能被 \(k-1\) 整除。


    联赛前写的题目,现在补一发题解。

    首先,这种写平均数的题目,我们可以想到建树,一个点对于答案的贡献就是 \(\frac{1}{k^{dep}} a_i\)

    这个时候,比较 naive 的想法,就是直接考虑每次操作了的 \(1\) 个数,但是显然会寄,因为可以操作 \(k\) 个,于是产生了进位。

    那么我们可以考虑最后的 \(k\) 进制小数,对于这个进行 DP,然后我们注意到对于原来的小数,每次进位后所有位置的数字和 \(\bmod~(k - 1)\) 的结果都是不会变化的,于是只要统计小数的数字之和 \(\bmod ~(k - 1)\)\(m \bmod (k - 1)\) 相同的小数即可。

    复杂度 \(\mathcal O(nm)\)↩︎

  10. AGC021C Tiling

    能否在 \(n\times m\) 的棋盘上放 \(A\)\(1\times 2\) 的砖和 \(B\)\(2\times 1\) 的砖?如果能,构造出方案。

    \(1\le n,m\le{10}^3\)\(1\le A,B\le 5\times{10}^5\)


    虽然没有看题解,但是并不是完全独立做出来的,因为 WA 到自闭了于是动用了魔法下了两个数据找到了叉点,于是过了。

    首先,在 \(n, m\) 中间有一个偶数的时候,不难得到策略(假设 \(n\) 是偶数):

    <><><><>^
    <><><><>v
    <><>^^^^^
    <><>vvvvv
    

    而且最多浪费 \(2\) 个:

    <><><><>^
    <><><><>v
    <><>^^^^^
    <>..vvvvv
    

    其他都是利用最大化了。


    对于 \(n, m\) 都是奇数的情况,我们可以照葫芦画瓢,再整一个类似的:

    <><><><>^
    <><><><>v
    <><><><>^
    <><>^^^^v
    <><>vvvv.
    

    最多浪费 \(3\) 个格子:

    <><><><>^
    <><><><>v
    <><><><>^
    <><>^^^^v
    <>..vvvv.
    

    然后交上去 WA 了 \(6\) 个点。

    下载数据发现是第二种情况有问题。

    手玩一下比较小的 case,然后发现在 \(3, 5, 5, 2\) 这种情况下,我们会:

    <><>^
    <><>v
    <>...
    

    然后就寄了。

    然后有更加优秀的做法:

    <><>^
    ^<>.v
    v<><>
    

    这个启发我们再拼上这种方案:

    <><><>^
    ^<><>.v
    v<><><>
    ^<><><>
    v<><><>
    

    这样两个方案综合,最多浪费一个格子。

    注意,我们优先使用 <> ,于是 <> 个数为 \(\max\{a, b\}\) (如果是 \(b\) 就交换行列构造,然后换回来),不然就会 WA 一个点。 ↩︎

posted @ 2022-07-29 19:28  Werner_Yin  阅读(104)  评论(1编辑  收藏  举报