[2024 AtCoder 比赛历程]
[2024 AtCoder 比赛历程]
ABC 337-G
题目大意:给定一棵树,对于树上的每个点\(u\),定义 \(f[u]\) 表示满足点 \(w\) 在点 \(u\) 到点 \(v\) 的路径中,且 \(w>v\) 的点对 \((w,v)\) 的数量。 \(u\) 可以等于 \(w\) 。
解法:比赛时先考虑将一个点钦定为 \(w\) 时,该点对其他点的贡献。发现对于一个点,它可以通过它的一个子树内比它要小的点,贡献到除这棵子树以外的所有点(子树包含“向上”的)。于是思考如何快速计算以某个点为根的子树中,有多少个点的编号小于某个点。比赛时想到用个可持久化线段树……但当然打不出来,赛后经过 lym 的启发,发现只用普通的树状数组就行了。我们只需要将树上的点从小到大加入,同时贡献。这样就避免了会统计到不该统计的点的问题。
ABC 338-D
题目大意:给定一个长度为 \(n\) 的环,以及一个长度为 \(m\) 的序列,现在需要在这个环上断掉一条边,问在最佳情况下,顺次走完(可以重复)序列中每一个点所需经过的最小边数。
解法:比赛中的做法不知道为什么一直炸,炸的还挺离谱。考虑枚举断掉的边然后计算贡献。对于序列中相邻的两个数,设小的为 \(a\) ,大的为 \(b\) 。若断掉的边在 \(a\) 至 \(b\) 的路径上,则贡献为 \(n-(b-a)\) ;反之则在 \(b\) 至 \(a\) 的路径上的贡献加上 \(b-a\) (表示选另外的一条路)。然后用差分做就可以了。
ABC 338-F
题目大意:给定一张 \(n\) 个点、 \(m\) 条边的有向图(n<=20),每条有向边有一个权值 \(w[i]\) (\(-10^{6}\le w[i]\le 10^{6}\)),问从任意一个点出发,经过所有点的最小的边权和,点和边可以重复经过。
解法:考虑最终的答案是由若干条从点 \(x\) 到点 \(y\) 的最短路径构成的。所以先处理出每两个点直接的最短路,然后进行转移。
注意事项:在有负边权的图中判断无解,需要考虑有可能一个点沿着一些负边移动的情况
不要乱用short
ARC 148-D
这题显然不是在比赛的时候做的。WC的时候题目选讲中的题目,但是是很好的博弈论。
题目大意:给定 \(2n\) 个数,\(A\) 和 \(B\) 轮流取数,取完后计算 \(A\) 取的数的和与 \(B\) 取的数的和在\(\mod m\) 意义下是否相等,如果不相等,则 \(A\) 获胜;否则 \(B\) 获胜。
解法:考虑最后只剩两个数的情况,发现只有最后的两个数\(a\)、\(b\) 满足\(a-b=b-a(\mod m)\) 时,\(A\) 无论取哪个数的结果都是一样的。所以我们可以把满足 \(a=b\) 或 \(a=b+m/2(\mod m)\) 两两配对。接着我们发现,对于 \(a=b+m/2(\mod m)\) 的数对,需要满足其有偶数个,\(B\) 才能获胜。所以我们总结一下 \(B\) 获胜的条件:需要有若干个满足 \(a=b\) 的数对和偶数个满足 \(a=b+m/2(\mod m)\) 的数对。
ABC 341-G
题目大意:给定一个长为 \(n\) 的序列 \(a\) ,然后对于每个位置 \(i\) ,求出以 \(i\) 为开头的前缀的平均值的最大值。
解法:相当巧妙。设 \(sum[i]\) 表示 \(a[1…i]\) 的总和,接着我们发现,求平均值的式子 \((a[j]-a[i-1])/(j-(i-1))\) 和求两点之间斜率的式子一样!所以我们将 \(a\) 上的每一个位置都变成一个点 \((i,sum[i])\) ,再加上一个 \((0,0)\) 。之后我们从后往前加入点,然后使用单调栈维护凸包,第一个没被踢出来的点即为答案的右端点。
ABC 361
好久没写了,到了暑假才开始写。而且这篇还是拖了好久的
赛时:B题一直想着 \(O(1)\) 判断,但是有很多情况要处理,一直在考虑如何考虑所有情况,导致WA了好多发。最后才想到可以暴力判断。D题的细节一直没处理好,不够仔细,也是罚了好多发,还影响了做E、F的时间。下一次在写题时要认真思考后再写,不要急。
成绩:Rank:849th,Performance 1703 ,Rating +44
ABC 361-G
题意:在第一象限(包含坐标轴)中,有 \(n(n<=2*10^5)\) 个石头,问所有满足 \(x>=0,y>=0\) 的点中,有多少个不可以通过上下左右移动走到 \((-1,-1)\) 的。
解法:既然是连通性问题,我们考虑用并查集。但是点数太多,所以我们使用缩点,将每一行中,从一块石头到下一块石头中间的所有点缩成一个大点。 我们通过在两边放一排石头,使得可以走到 \((-1,-1)\) 的点放到一个并查集里,注意要在两边多留一条空隙。最后将每一行的大点依次合并,用总数减掉 \((-1,-1)\) 所在的并查集的大小和石头数量就是答案
ABC 362
原题大赛,打的还不错,上了 \(90+pts\) 。
ABC 362-F
题意:给定一棵树,需要你输出 \(\left \lfloor n/2\right \rfloor\) 个点对,使得这些点对的距离之和最大。
解法:考场上想到重心,如果说一棵子树和另一棵子树之间的点能够刚刚好配对,那么无论配对方法是什么,对答案的贡献是不变的,而且是最优的。然后我就开始尝试用各种方法合并子树,最后都WA掉了。发现我们只要把每个子树内的所有点放入一个数组内,如果 \(n\) 为偶数,那么将重心也放进去,最后将下标为 \(x\) 与 \(\left \lfloor x/2\right \rfloor\) 的两个点合并就好了。因为重心的子树大小不会超过 \(\left \lfloor n/2\right \rfloor\) ,所以这样做是正确的。
ABC 364
在打 D 题的二分时有点犹豫,还需加强二分的能力。E 题的DP没有想到这样的一个套路,还要多练习。
ABC 364-E
题意:给定 \(n(n\le 80)\) 道菜,每道菜有两个属性 \(x\) 和 \(y(x,y\le 10000)\) ,可以按照任意顺序吃,但是如果吃掉的菜的 \(\sum x>X\) 或\(\sum y>Y\) ,则不能继续吃了,问最多吃多少道菜?
解法:很容易想到的一个DP是:设 \(f_{i,s1,s2}\) 表示当前吃到第 \(i\) 道菜,吃完的菜的属性 \(x\) 的总和为 \(s1\) ,属性 \(y\) 的总和为 \(s2\) ,值为最多吃多少道菜。但是这样的状态数太多了,我们发现这个DP的值域为 \(n\) ,很小,于是我们考虑更换一下状态。设 \(f_{i,j,s1}\) 表示当前吃到第 \(i\) 道菜,吃了 \(j\) 道菜,吃完的菜的属性 \(x\) 的总和为 \(s1\) ,值为吃掉的菜的属性 \(y\) 的总和,这样就可以大大减少状态数。
ARC 181
这几天打得都不好,一直掉分。我觉得我的问题在于一直跟着自己一开始的思路走,很少会去推翻重想,不停地试着去补足假做法。以后要换一种想题的方式,毕竟想 \(Atcoder\) 这样的比赛,不能浪费太多的时间。如果一个做法很难实现或会有很多不足的话,尽量就不要继续想了。
ARC 181-B
题意:给定三个字符串 \(S,a,b\) ,其中, \(S\) 由小写字母组成, \(a,b\) 由 \(0,1\) 组成,若 \(a\) 的第 \(i\) 个字符为 \(0\) ,则在一个初始为空字符串 \(A\) 的末尾加上字符串 \(S\) ,若为 \(1\) ,则在末尾加上一个字符串 \(T\) ;\(b\) 同理。问是否存在一个字符串 \(T\) ,使得 \(A=B\) 。
解法:设 \(S\) 的长度为 \(len1\) ,\(T\) 的长度为 \(len2\) 。假设 \(len1>len2\) ,则我们将 \(S\) 变为 \(S'+T\) ,其中 \(|S'|=len1-len2\) ,然后带入原式;若 \(len1<len2\) ,那么就反过来。直到 \(len1'=len2'\) ,此时两个式子是相等的,那么我们只需要判断 \(S\) 中是否存在长度为 \(len1'\) 的循环节就好了。求 \(len2\) 时可以列一个方程来求,如果无解那么 \(T\) 就不存在。
ARC 181-C
题意:给定两个 \(n\) 的排列 \(a,b\) ,需要构造出一个 \(n\times n\) 的 \(0/1\) 矩阵,使得每一行的字符串按字典序排序后的编号为 \(a\) ,每一列的字符串按字典序排列后的编号为 \(b\) 。
解法:手玩数据发现可以这样构造:先将矩阵中满足 \(i+j\ge n+1\) 的位置填满 \(1\) ,其余位置填 \(0\) ,然后将第 \(i\) 行填到满足 \(a_j=i\) 的第 \(j\) 行,再将第 \(i\) 列填到满足 \(b_j=i\) 的第 \(j\) 列。(为什么别人玩的出来我不行……)
ABC-366
上分好耶。G 题的知识点不难,但是我还是不会。要好好补一补小的知识点了。
ABC-366 G
题意:给定一个 \(n\) 个点, \(m\) 条边的无向图( \(n\le 60\) ),需要你给每个点赋一个值域在 \([1,2^{60}-1]\) 的值,要求每个点连向的点的异或和为 0 。
解法:考虑使用高斯消元异或方程组,根据顶点关系,我们可以列出方程组。接下来的消元也不难,关键在于对自由元的取值。若变量 \(i\) 位自由元,则我们将其赋值为 \(2^i\) ,因为它能够影响到的变量都\(<i\) 。但是好像不要取一些看上去就会错的值都可以(如1/0),有人取了 \(2^i-1\) ,有人直接 \(rand\) 。
还有一种做法是对于每一位做一遍高斯消元,每一个强制钦定某个自由元为 1,这样也可以避免取到 0 的情况。
有一个小地方,我以前没有注意到,就是在代码中出现的数字 \(1\) 它好像默认是 \(int\) 类型的,不能 \(1<<32\) 。
ABC-367
反复领会不罚时的重要性。自己想到解法的速度是很快的,但是对于细节的处理还是不够。还是得好好检查思路再来打。
E 题使用倍增相当好写,但是我当时看到环就在想循环节,分类讨论的情况多。
ABC-367 G
FWT,等学了再来
AGC-067
AGC-067 A
题意:给定一个无向图,问你这个图是否满足它的每个生成子图都存在一个大小至少为该生成子图大小的一半的团。
解法:结论:如果整个图可以被划分为至多 2 个团的话,答案为 Yes
。
证明:我们发现,对于一个奇数 \(x\) ,如果大小为 \(x\) 的生成子图可以被满足/不满足,则大小为 \(x+1\) 的生成子图也可以被满足/不满足。于是我们只用考虑更小的 \(x\) 。我们考虑对于 \(x\) 个点,如何构造一个边数尽可能多的图,使得这个图不能满足条件。发现当我们构造出来的图的补图存在一个 \(x\) 元环时,条件不会被满足。
所以我们在原图上的补图进行黑白染色,如果可以满足条件,则答案为 Yes
。对于一个大小为 \(x\) 的团,它需要 \(\frac{d*(d+1)}{2}\) 条边,由于 \(m\le 10^6\) ,所以 \(n\) 最大为 \(2002\) 。
ARC-183
军训期间没得打AT,暑假结束了还没有上到蓝名,可惜。
ARC-183 C
题意:给定 \(m\) 个条件,每个条件表示区间 \([l,r]\) 中的最大值不能在位置 \(x\) 上。问 \(n(n\le500)\) 的排列中有多少满足所有的条件。
解法:还是DP题做少了,计数DP的套路题都不会。容易想到区间DP,设 \(f_{l,r}\) 表示区间 \([l,r]\) 中,填入 \(1...r-l+1\) 这些数时,满足条件的有多少个。转移时枚举一个可以成为最大值的位置 \(k\) ,\(f_{l,r}=f_{l,k-1}*f_{k+1,r}*\binom{r-l}{k-l}\) ,由于我们只记录了相对的大小,所以最后要乘上组合数,表示这些数字要放在左边还是右边。
ARC-183 D
题意:给定一棵树,满足 \(2i\) 与 \(2i+1\) 有连边。每次要选出两个叶子节点,将它们删除并且保证操作完的树仍是完美匹配,这次操作的贡献为选取的两点之间的距离。需要输出一种操作方案,将整棵树删掉,并使得贡献之和最大。
解法:首先要求贡献最大,联系之前做过的一道题就知道要以中心为根。接下来考虑如何删才能使得树仍然合法。我们随便取一个完美匹配,然后将匹配中的边标为 1,不是匹配中的边标为 0,然后我们可以发现,当两个点 \(x,y\) ,它们之间的路径为 01 交替时,它们就可以被删掉,并且路径上的边全部取反(异或上1)。而只有与重心 \(K\) 连了题目中保证的特殊边(\(2i\) 与 \(2i+1\))的点,以该点为根的子树中,才会出现 1 的边。然后进行了一次操作后,另一个删除的点所在的子树又会出现 1 的边,而该子树中没有了 1 的边。所以我们每次取大小最大的子树与存在 1 边的叶子进行配对,然后不断重复,最后一个点与根配对。
最后还有一个问题,我们要保证删除的点到根的路径上的边是 01 交替的,所以我们在 \(dfs\) 时先搜索 0 的边,然后按照 \(dfn\) 从大到小取就好了。
ABC-370
终于上蓝名了,1605 Rating,还要防掉。累。
ABC-370 F
题意:给定一个环,环上的每个点有一个权值 \(a_i\) ,需要将这个环拆成若干个连续的区间,使得所有区间的总和的最小值最大。问这个值,以及所有满足最小值为这个值的方案中,有多少条环上的边不会被断开。
解法:比赛时没有想到倍增,导致二分时判断答案那里一直不会做。
看到最小值最大可以想到二分答案,设 \(mid\) 表示拆开的区间和的最小值为 \(mid\) 。然后将环复制一遍,变成序列。对于一个点 \(i\) ,我们贪心地将它指向最近的一个 \(j\) ,满足 \(i...j-1\) 的总和 \(\ge K\) ,表示选取一个合法的区间。然后倍增,设 \(f_{i,j}\) 表示第 \(i\) 个节点,跳了 \(2^j\) 个区间后会到哪个节点。最后我们判断这个节点与初始节点是否构成一个长度 \(\le n\) 的区间。
对于第二个答案,我们求出在上述过程中,有多少个点 \(i\) 是合法的就行了,表示我们一定会拆掉 \(i\) 前面的那条边。
ABC-371
做简单题的速度很快很准,\(25min\) 把 \(A...E\) 切了,但是在思考的时候还不够全面,二分不够熟练,对于细节的处理也没有搞好,导致 F 做得慢还没有在考场上调出来。
ABC-371 F
题意:在一个一维平面内有 \(n\) 个点,这些点每次可以向左移动一格或向右移动一格,但是移动完后不能有两个点重合。现在有 \(m\) 个操作,第 \(i\) 个操作要求将 \(x\) 移动至位置 \(k\)。问完成这些操作的最小步数和。
解法:考虑如何快速算出一次操作会影响到那些点。当我们得知会影响哪些点后,求答案就是用区间和减掉最终状态。假设点 \(i\) 的位置 \(x<k\) ,那么对于 \(>i\) 的 \(j\) ,如果它满足 \(x_j<k+(j-i)\) ,那么它就会被影响。我们将上面的式子移项得: \(x_j-j<k-i\) 。这启示我们将一个数的位置 \(x\) 减掉下标 \(i\) 变成新的位置 \(x'\) ,发现这样做不仅可以避免求会影响哪些点时,出现要判断当前点是否会影响后面的点的情况;还可以简化修改。于是我们开一棵线段树存新的位置的区间和、\(max\) ,然后在线段树上二分可以求出会影响哪些位置,然后求区间和算答案即可。
ABC-371 G
题意:给定两个排列 \(a,p\) ,可以执行无穷多次操作,每次同时将所有的 \(a_{p_i}\) 变成 \(a_i\) 。问可能得到的最小的序列 \(a\) 的字典序为多少。
解法:先将所有的环找出来,然后贪心地考虑每个环上的数的位置。设最终要执行 \(C\) 次操作,则我们每次确定一个长度为 \(l\) ,在满足前面的限制下,最优的位置会由操作 \(x\) 次得到的环,就会产生一个 \(C\%l=x\) 的限制。我们考虑暴力地判断是否满足条件。对于两个长度相等的环,后面的环的操作一定是和前面的一样;对于其他情况,我们暴力枚举 \(x\) ,然后判断是否满足所有限制条件,最后取满足限制条件的最小的就行了。时间复杂度为 \(O(n\sqrt n\log n)\) 。
ABC 374
连着两场没有切掉 E 了,掉回青名了,\(QwQ\) 。
ABC 374-E
题意:给定 \(n\) 个选择,第 \(i\) 个选择可以从两种机器中选出若干个,机器分别是花费 \(c_i\) 元可以获得 \(a_i\) 个单位的产品和花费 \(d_i\) 元可以获得 \(b_i\) 个单位的产品。问在给定总费用上限 \(X\) 后,能够在每个选择中获得的产品的最小值最大是多少?
解法:比赛时列了一个函数,还以为它是单峰,结果因为这个挂了。
首先二分答案 \(mid\) 。然后考虑如何计算每个取到 \(mid\) 个时的最小钱数,考虑购买性价比高的,但是又不一定最优。此时注意到 \(a_i,b_i\le100\) ,假设第一个机器的性价比更高,则有 \(c/a<d/b\) ,那么当我们购买了 \(b_i\) 个第二个机器时,肯定不如用这些钱购买第一个更优,于是我们枚举性价比低的机器的购买个数,然后算出另一个机器的购买个数,取最小钱数就好了。
ABC 374-F
题意:给定 \(n(n\le100)\) 个货物,每个货物有一个可以开始发货的时间 \(T_i(T_i<=10^{12})\) ,每次可以同时发最多 \(K\) 个货,每发一次货就有 \(X\) 的发货冷却。定义不满意度为第 \(i\) 个货物被发送的时间与 \(T_i\) 之差。问最小的不满意度之和。
解法:设 \(f_{i,j}\) 表示当前的时间为 \(i\) ,已经发送了前 \(j\) 个货。由于时间可能非常大,无法直接DP。但是发现 \(n\) 很小,通过贪心发现有用的时间点只有 \(O(n^2)\) 个,对于每个时间点额外记录 \(n\) 个时间点 \(T_i+X*a(1\le a\le n)\) ,这样就减少了第一维的数量。我们继续贪心,考虑到每到达一个时间点,我们要么不发送,要么尽可能多发。于是可以设计出转移式。时间复杂度 \(O(n^3)\) 。
ABC 374-G
我!怎!么!不!会!\(tanjan\) !
题意:给定 \(n\) 个长度为 2 的,由大写字母组成的字符串。需要将这些字符串首尾拼接起来,一个字符串可以使用多次。问至少需要拼接成多少个字符串,使得 \(n\) 个字符串都被用到。
解法:最小路径覆盖的题。由于是一般图,所以先将每个字符串向能够拼接在它后面的字符串连边,然后跑 \(tanjan\) 缩点。接着对缩过点的图进行操作。这里的最小路径覆盖是可以重复经过一条边的,所以我们跑一遍 \(Floyed\) ,将每个点向它的子树内的所有点连边,这样问题就转化为不可以经过重复路径的了。接下来我们对于图上的每一个点,将它拆成两个,对于每一条边 \(x\to y\) ,将 \(x\) 拆出来的第一个点连向 \(y\) 拆出来的第二点。然后从源点向所有拆出来的第一个点连边,所有拆出来的第二点向汇点连边。以上连的边的流量均为 1 。然后我们跑出这个图的最大流,此时 点数-最大流 即为答案。这里可以感性理解一下,对于每个没能对最大流进行贡献的点,没有点流向它,即它将成为一条路径的开头,我们最大化非路径的开头的点数,就可以最小化路径数。
由开头可知,这道题对于笔者的难度不在于后面的网络流,所以补一下 \(tanjan\) 。
我们从有向图中任意一个没有被遍历过的点跑 \(tanjan\) 。我们需要求出每个点的 \(dfn,low\) ,分别表示一个点被遍历的顺序和它能够到达的所有点的最小的 \(dfn\) 。再维护一个栈,里面存放所有 搜过的点。
搜索过程中,对于 \(x\) 连向的一个点 \(y\) ,当它还没遍历过时,我们先搜索它,回溯后根据 \(low\) 的定义,将 \(low_x\) 更新为 \(min(low_x,low_y)\);当它已经被遍历过而且在栈中时,我们将 \(low_x\) 更新为 \(min(low_x,dfn_y)\);当它已经被遍历过而且不在栈中时,我们不需要进行任何操作,因为如果它会和当前的 \(x\) 产生强联通分量,那么在它被搜索的时候已经处理掉了。回溯时,对于一个点 \(x\) ,如果它满足 \(dfn_x=low_x\) ,那么我们进行弹栈,直到将 \(x\) 弹出,这些弹出的点都会和 \(x\) 缩在一个强联通分量中。
ABC 375
第一次AK!!!开心!
感谢昨天才打的 \(tanjan\) 。
做E、F的时候人傻了,E题甚至打了个费用流,F题打了个暴力。打之前要想想正确性,算一算复杂度,避免罚时。
ARC 185
还是有很多知识不会,例如 C 题的 NTT 和 E 题的欧拉函数,了解的不够多,需要慢慢发掘,及时补足。
ARC 185-E
题意:给定一个长度为 \(n(n\le 5*10^5)\) 的序列 \(a\) ,其中 \(a_i\le10^5\) 。定义一个序列的权值为该序列相邻两个数的 \(gcd\) 之和。对于 \(i\in[1,n]\) ,求出 \(a\) 序列的前 \(i\) 个数构成的序列的所有子序列的权值。
解法:首先可以将题目要求的东西转化为:设 \(ans_i\) 表示 \(i\) 的答案,则 \(ans_i=2*ans_{i-1}+\sum_{j=1}^{i-1}2^{j-1}gcd(a_i,a_j)\) ,由于对于任意的正整数 \(n\) ,都有 \(n=\sum_{d|n}\varphi(d)\) ,然后我们接着变式子:
此时我们可以预处理出所有的 \(\varphi(d)\) ,并且开一个数组,记录所有 \(i\) 之前的数对于 \(a_j\) 的因子 \(d\) 的贡献,就可以快速计算后面的一个 \(\sum\) 。
ABC 376
C 题成为最大滑铁卢。因为自己习惯设 \(inf=10^9\) ,然后它的数据范围就是 \(\le10^9\) ,然后一直有一个点过不去,以后要把这个习惯该掉,再设大一点。
ABC 376-G
题意:给定一棵以 \(0\) 为根, \(n+1\) 个节点的树 \((n\le 2e5)\) 。每个节点上有一个权值 \(a_i\) ,表示在该点找到宝藏的概率为 \(\frac{a_i}{\sum a_j}\) 。当一个节点的父节点被探索过后,该节点才可以被探索。现在只有节点 0 被探索了,问按照最优策略找到宝藏的最小期望是多少,对 998244353 取模。
解法:首先我们发现一个节点的子树内的点会对我们的选择有影响,所以我们考虑对于整张图如果去掉了 “只有父节点选了之后才能选” 的限制后如何处理,那么我们只需要将所有的 \(a_i\) 丢进一个堆里,每次取出最大的就好了。此时,假如我们取出来一个节点,在限制下其实是无法探索的,那么我们在探索完它的父节点后,一定会先探索该节点。这样我们可以考虑把该节点和它的父亲合并起来,并赋予一个新的权值。那么我们现在需要找到一个正确的权值比较方法。
先将答案的式子写出来:\(\sum a_{p_i}i\) ,其中 \(p\) 是按最优策略选出来的一个排列。对于与 \(i\) 合并了的点构成的连通块,设只探索该连通块对答案的贡献为 \(val_i\) ,该连通块的概率总和为 \(sum_i\) 。假设连通块 \(i\) 的次序在连通块 \(j\) 前面,那么就要满足 \(val_i+siz_i*sum_j+val_j<val_j+siz_j*sum_i+val_i\) ,解出来就是 \(\frac{sum_i}{siz_i}>\frac{sum_j}{siz_j}\) 。于是我们根据这个式子,将所有的点丢进一个堆里,然后将每次取出来的节点和父亲合并,并记录取出来的顺序。最后按照这个顺序跑一遍,注意和父亲合并,计算结果就好了。
ARC 186
不会计数题,大失败。于是一直在做 T3 ,一开始的思路把自己弄晕了,应该根据放球的人的策略先写出答案的式子再继续去推。
ARC 186-A
题意:定义两个大小为 \(N*N(N\le30)\) 的01矩阵是相似的,当且仅当它们每一行每一列上的数之和都与另一矩阵对应的行和列上的数之和相等。定义01矩阵 \(A\) 中一个位置是固定的,当且仅当对于与 \(A\) 所有相似的矩阵 \(B\) ,该位置上的值不变。有 \(Q\) 个询问,每次问你是否存在一个01矩阵满足该矩阵上所有固定的位置的数量等于 \(K_i\) 。
解法:考虑如何从一个矩阵变换到一个相似的矩阵。不难发现如果存在一个矩形满足它对角上的位置的数相等且相邻的顶点上的数不相等,那么就可以将这四个位置上的数进行交换。发现这个条件是充要的。接着考虑怎么使用这个结论。我们可以选择一些矩形,使得在同一行或同一列中至多只有一个矩形,然后我们在这些矩形中交替地填上 01 ,对于不在矩形中的位置,我们可以通过右上半部分填 1 ,左下填 0 的方式,使得只有这些矩形中的点不固定,而且不同矩形中的点互不干扰。于是就可以 DP 了。时间复杂度 \(O(N^6)\) 。
ARC 186-B
题意:给定一个长为 \(n(n\le 3*10^5)\) 的序列 \(a\) ,第 \(i\) 个数字 \(a_i\) 满足 \(0\le a_i<i\) ,表示对于所有的 \(a_i<j<i\) ,在一个 \(n\) 的排列 \(b\) 中都要有 \(b_j>b_i\) ,且 \(b_{a_i}<b_i\) 。问有多少个排列 \(b\) 满足所有条件,对 \(998244353\) 取模。
解法:通过不等式,我们可以从小的连向大的,这样问题就变成了拓扑序计数。但是这个问题是 NP 的,所以我们考虑寻找一些性质。我们通过那些从 \(a_i \to i\) 的边建出一棵树,发现对于一个点,它如果可以被取出来,当且仅当比它编号大的兄弟和父节点都被取出来了。于是我们可以根据这个性质从下往上处理出每一棵子树内全部取出的方案数,然后用组合数去求就好了。
具体求的方法是:每次合并两棵子树,相当于把编号大的那棵子树的根节点拿走,剩下的节点去做插板,然后将那个点放在序列最前面。但是这样只可以从编号小的开始合并,不然会出问题(可手模一个节点,有三个大小不小于2的子树的情况)。
ARC 186-C
题意:有两个人在玩游戏,第一个人有 \(M\) 种颜色的球,每种球有无数个,同时有 \(N(N\le3*10^5)\) 个盒子,每个盒子有价格 \(p_i\) 和体积 \(v_i\) 。现在第一个人每次要给第二个人一个球,第二个人可以在任意时刻购买盒子,并把球放到一个已经购买的盒子里去。一个盒子里的球只能有一种颜色,且球的数量不能超过体积。每成功放入一个球,第二个人可以获得 1 元,否则游戏结束。第二个人可以在任意时刻结束游戏,且钱数可以为负数。现在第一个人想要让第二个人的最终钱数尽量少,第二个人想要自己的最终钱数尽量多,问如果两人均以最优策略进行游戏,第二个人的最终钱数是多少?
解法:考虑第一个人的最优策略:不管第二个人买了多少盒子,他只需要尽量减少第二个人能放球的机会就行了。所以第一个人一定先给第二个人 \(M\) 种颜色的球各一个,然后再选择 \(v\) 最小的、已经被购买的盒子进行填满,并不断重复。
因此第二个人最终购买的盒子中, \(v\) 前 \(M-1\) 大的是一定不能够填满的。所以我们先将所有的盒子按 \(v\) 从大到小排序,接着枚举分界点 \(i\) ,表示 \(i\) 之前的盒子如果购买了,那么一定无法被填满;而 \(i\) 之后的盒子如果购买了,是可以填满的。对于前面的一部分,我们贪心地去选出 \(p\) 最小的前 \(M-1\) 个,对于后面的部分,我们贪心地选择所有 \(v-p>0\) 的盒子即可。
ARC 186-D
题意:定义一个序列是 \(\text{Polish}\) 的,当且仅当将它的开头 \(a_1\) 取出来后,剩下的序列可以被拆分成 \(a_1\) 个连续的序列,且这些序列都是 \(\text{Polish}\) 的。特别的, \(\{0\}\) 为 \(\text{Polish}\) 的。
现在给定一个长为 \(n(n\le3*10^5)\) 的序列 \(a\) ,问有多少个长度为 \(n\) 的 \(\text{Polish}\) 序列满足它的字典序不大于 \(a\) 。对 \(998244353\) 取模。
解法:由于一个 \(\text{Polish}\) 序列的最后一位是确定的,一定为 0 ,所以我们考虑从后往前如何构造一个 \(\text{Polish}\) 序列。通过手玩可以发现,一个位置如果填 \(x\) ,则它可以和它后面的 \(x\) 个 \(\text{Polish}\) 序列合并成一个 \(\text{Polish}\) 序列。如果 \(x\) 填 0 ,则它自己变成一个 \(\text{Polish}\) 序列。如果后面不足 \(x\) 个 \(\text{Polish}\) 序列,则该位置填 \(x\) 是不合法的。如果开头没有把所有的 \(\text{Polish}\) 序列合并,那么也是不合法的。我们将这个判断的方法写成式子:\(\forall i\in[1,n],\sum_{j=i}^na_j\le n-i;\sum_{j=1}^na_j=n-1\) 。
接下来我们根据这个式子求方案数,我们可以先将这个式子对称,变成对前缀进行限制,容易处理。先不看字典序的限制,求该式子的方案相当于将 \(\sum a_i\) 当作 \(x\)轴 , \(i\) 当作 \(y\)轴,从点 \((0,1)\) 走到点 \((n-1,n)\) 且不经过直线 \(y=x\) 的方案数。求这个方案数可以利用对称,假设当我们走到不合法的直线上时,我们以后的路径关于 \(y=x\) 对称,于是终点就变成了原来的终点关于 \(y=x\) 对称的点。所以我们先求一遍到原来的终点的方案数,减去到对称的点的方案数就行了。
接下来考虑加入字典序的限制。由于我们对序列进行了翻转,所以我们每次修改的是终点。枚举当 \(i\) 之前的位置都取到最大值时,\(i\) 没有取到最大值的所有情况。由于最多走到 \(n-1\) ,实际上它最多只需求 \(n-1\) 次。最后再判断一下 \(a\) 是不是 \(\text{Polish}\) 序列就行了。
VP AGC 037
\(ky\_star\) 大法好。
AGC 037-B
题意:给定由三种颜色、每种颜色有 \(n(n\le 2*10^5)\) 个的字符串,需要给 \(n\) 个人分配不同的三种颜色。定义一个人产生的代价为:他分到的颜色在字符串中的位置的 最大值-最小值 。问使所有人产生的代价和最小的方案数有多少?对 \(998244353\) 取模。
解法:考虑一步一步做,先将一种方案求出来。可以贪心地去求一组方案,当枚举到一个没有被取过的颜色时,我们找到在它之后最近的其他两种颜色,然后将它们按顺序标记为 \(-1,0,1\) 。这些数字表示它们对代价和的贡献。
接着考虑计算方案数。对于一个 \(0\) ,它可以和前面的 \(-1\) 分配在一起,但是要减去已经被分配了的 \(-1\) 的个数。\(1\) 同理。最后由于 \(n\) 个人有标号,所以要乘上 \(n!\) 。
AGC 037-D
题意:给定一个 \(n*m(n,m\le100)\) 的矩阵,其中填满了 1 到 \(n*m\) 这些数。需要按顺序执行以下操作,分别是:
- 重新排列每一行;
- 重新排列每一列;
- 重新排列每一行。
需要构造一种方案,使得最终的矩阵满足格子 \((i,j)\) 上的数为 \((i-1)*m+j\) 。
解法:观察样例,设最终矩阵中,每一行上的数为一组。第一步操作需要我们将每一列上的数排列成两两之间不能为同一组,第二步操作需要我们将同一组的数放在同一行。第二步是容易的,接下来考虑第一步要如何去做。
根据数据范围,想到网络流。将每一组的点染成一种颜色,然后每一行视为一个点,将该点向该行上所有的颜色连边。这个问题可以对于每一列按顺序处理,所以就是要对于每一列,求出一个完美匹配。跑 \(m\) 次最大流就好了。
ABC 379
太可恶了,C题少了特判石子多余的情况,差一点就 AK 了。而且由于自己没有 Rating ,导致打的时候不是很专注,以后要准时参加,要 Rating 。
VP AGC 020
AGC 020-C
题意:给定一个长度为 \(n(n\le2000)\) 的集合,\(a_i\le2000\) ,问这个集合的所有子集的元素和(不算空集)构成的序列的中位数。
解法:设 \(sum\) 表示集合的元素和。考虑一个子集和它的补集,它们的元素和相加一定等于 \(sum\) ,而且我们不计算空集,所以答案即为能构造出来的 $\ge\left \lceil\frac{sum}2\right \rceil $ 的第一个数。使用 DP + bitset 优化解决。
AGC 020-D
题意:有 \(Q(Q\le 10^3)\) 次询问,每次询问给定四个数 \(a,b,l,r(r-l+1\le100;a,b\le10^8)\) 。需要你构造一个由 \(a\) 个 A 和 \(b\) 个 B 组成的字符串,需要它最长的同种颜色段尽量短,在此前提下满足该字符串的字典序最小。需要输出第 \(l\) 个字符到第 \(r\) 个字符。
解法:先求出最长的相同颜色段的长度,设其为 \(k\) ,则 \(k=\left \lceil\frac{max(n,m)}{min(n,m)+1}\right \rceil\) 。接着手模几个数据,观察一下,发现字符串大概是长成这样:分成前后两段,前面一段从前往后由 \(k\) 个 A 和一个 B 这样的小段不断重复排列;而后面一段从后往前是由 \(k\) 个 B 和一个 A 这样的小段不断重复排列。而且在分界线的左边为 A,右边为 B。
那么我们二分该分界线,后半部分需要满足 \(b>a*k\) 。然后分两半输出就好了。
ABC 380
没打出来 F ,没有想到如何计搜,状态还是不大好。
ABC 380-F
题意:有两个人 A、B,A手上有 \(n\) 张牌,\(B\) 手上有 \(m\) 张牌,桌面上有 \(K\) 张牌 \((n+m+K\le12)\)。\(A\) 先手,每次轮到一个人可以有两种操作:一是将手上的一张牌与桌面上点数小于该牌的牌交换,二是将手上的一张牌放到桌牌上。谁不能操作谁输,问谁会获胜?
解法:由于牌的总数很小,所以使用 三进制状压+记忆化搜索决策树 解决。注意记忆化时要记录是谁的回合。
ABC 380-G
题意:给定一个 \(n(n\le2*10^5)\) 的排列和一个常数 \(K(K\le n)\) ,问在排列中随机选取一个长度为 \(K\) 的子序列,然后随机打乱后得到的排列中,逆序对的期望个数。答案对 998244353 取模。
解法:考虑直接计数。首先可以通过不断加入一个数,推出 将一个长为 \(x\) 的排列打乱后的逆序对期望个数。设 \(f_x\) 表示期望个数,则 \(f_x=x*f_{x-1}+\frac{x*(x-1)}2*(x-1)!\) 。然后剩下的部分就是使用一个移动窗口,每次计算整个排列中,不算移动窗口中的数的逆序对数量。
ARC 187
怎么不会B?
ARC 187-B
题意:对于一个序列 \(A\) ,定义 \(f(A)\) 表示将序列 \(A\) 中每对满足 \(i<j,a_i\le a_j\) 的 \((i,j)\) 连一条无向边,最终得到的图的连通块数量。现在给出一个长度 \(n\) 的序列 \(a\) 和一个常数 \(m(n,m\le2000)\) ,满足 \(a_i\) 要么等于 -1 ,要么在 \([1,m]\) 内。问将所有 -1 替换成 \([1,m]\) 中的一个数后,得到的所有序列 \(a'\) 的 \(f(a')\) 的和。答案对 998244353 取模。
解法:先找出产生一个连通块的判断方法。若 \(i\) 满足它的前缀 \(min\) 大于 \(i+1\) 的后缀 \(max\) ,则 \(i\) 之前的数不会与 \(i+1\) 之后的数连边,于是产生了一个连通块。那么我们就通过这个结论,用组合数算一下就好啦。
VP AGC 019
AGC 019-D
怎么都想到结论了还是做不出来?
题意:给出两个长度均为 \(n(n\le2000)\) 的 01序列 A、B。现在有三种操作:将 序列A 整体向左移或向右移,超出的部分在另一边补;对于一个 序列B 上的 1 ,将 序列A 的对应位置上的数取反。问最少操作多少次可以使 A 变成 B 。
解法:由于不好判断一系列操作后的 A 能否通过移动得到 B ,再加上 \(n\le2000\) ,考虑钦定最终是哪些点需要变为 1 。那么其余需要从 1 变成 0 的位置就要在移动过程中操作。处理出每个位置向左和向右的第一个 B 上的 1 在哪里,如果一个位置不能在移动过程中被操作成 0 ,就需要额外跑一下。那么我们贪心地去做,将所有需要变换的位置放在一个数组里排序,那么钦定某个位置为分界线,该位置左边的点全部向左跑,右边的点全部向右跑,后缀\(max\) 处理一下就好了。
AGC 019-E
题意:给定两个长度为 \(n(n\le10^4)\) 的 01序列A、B,两个序列的 1 的数量相同,设 A 序列中 1 的位置分别为 \(a_1,a_2...a_k\) ,B序列中 1 的位置分别为 \(b_1,b_2...b_k\) 。将 \(a,b\) 两个数组随机打乱后,对于每个 \(i\in[1,k]\) ,按小到大的顺序将 A序列 中位置为 \(a_i\) 和 \(b_i\) 的两个数交换。问最后 A序列 和 B序列 相同的期望。乘上 \((k!)^2\) 后对 998244353 取模。
解法:不会生成函数解法……
将原序列中同一个 \(i\) 在 A、B 上的数绑在一起考虑。
那么当这个数为 00 时,我们不会操作它,不用考虑;
当这个数为 10 时,它将成为某次交换的起点,因为它会将 1 交换出去;
当这个数为 01 时,它将成为某次交换的终点,因为它需要一个 1 ;
当这个数为 11 时,它将成为某次交换的中转点,因为它可以交换两次。
我们设 起点/终点 的个数为 \(m\) ,中转点的个数为 \(n\) 。那么将每个点向它要交换的点连边后,整个图就是 \(m\) 条链以及若干个环。考虑环如何处理。设 \(f_{i,j}\) 表示当前使用了 \(i\) 个中转点,构成了 \(j\) 条链,那么转移就是:
- 加入一个中转点,将它放在某一个链的末端,考虑加入的链与标号:\(f_{i-1,j}*i*j\to f_{i,j}\)
- 增加一条链,放在所有链的最后,考虑起点与终点的标号:\(f_{i,j-1}*j^2\to f_{i,j}\)
发现题目中的操作序列实际上是有顺序要求的,这里的顺序要求实际上通过转移顺序解决了。
那么接下来处理环的情况,设有 \(i\) 个点构成了环,那么需要在 \(n\) 个中转点中选出 \(i\) 个,给它们标号和顺序,再乘上链的方案数,以及将它们插入整体的顺序的方案数。
AGC 019-F
题意:有 \(n+m(n,m\le5*10^5)\) 道判断题,其中有 \(n\) 道是对的,\(m\) 道是错的。每回答一道题就可以知道该题的答案。问在最优答题策略下,期望答对几道题?对 998244353 取模。
解法:钦定 \(n>m\) 。先考虑最优策略:当 \(n,m\) 不相等时,回答最大的那个;当它们相等时,回答任意一个都可以,不妨设为回答 \(n\) 。那么可以建出网格图,每答一题就相当于在上面走 横坐标或纵坐标-1 的一步,将最优策略构成的路线在网格图上画出来,然后答案就变成了 所有正确答案构成的路线与最优策略重合的长度 除以 \(\binom{n+m}n\) 。
发现如果没有在直线 \(y=x\) 上向下走的那一部分是很好求的,期望为 \(n\) 。那么我们特别处理这一部分,那么就是对于每个 \((i,i)\) ,求出经过 \((i,i)\) 和 \((i,i-1)\) 的路径数既可。最终答案除以总方案数加上前半部分的 \(n\) 就好了。