五月杂题选做(part 2)

上回说到:2022.5 part 1

关于难度

可以秒杀的题。

思考一会儿后可以秒的题。

需要较长时间思考的题。

看题解、稍加指点就会做的题。

看题解后需要较长时间消化,甚至现在都没有完全理解的题。


ARC106D *1988

已知一个长度为 n 的序列 ai 和一个数 k,对于所有 1Xk,求

i=1nj=i+1n(ai+aj)X

答案对 998244353 取模。
n2×105,k300

标签:组合。

直接二项式定理展开,推式子就好了。

i=1nj=1n(ai+aj)X=i=1nj=1np=0X(Xp)aipajXp=X!i=1nj=1np=0Xaipp!ajXp(Xp)!=X!p=0X(i=1naipp!)(j=1najXp(Xp)!)

可以发现是一个卷积,记 fi=j=1najii!,答案就可以直接卷积得到,暴力卷积即可,时间复杂度 O(k2+nk)

code


ARC113D *1389

对于一个 n×m 的矩阵,每个元素都 1ai,jk,定义 ai 表示第 i 行的最小值,bi 表示第 i 列的最小值,已知 n,m,k,求有多少个不同的 (a,b),答案对 998244353 取模。
n,m,k2×105

标签:计数。

最简单的一个 ARC D,但还是想了一会儿的。

考虑一个很简单的东西,就是 max(ai)min(b) 这个东西可以很简单可以证明,然后可以发现,除非矩阵只有一行或一列,否则只要满足上面条件的 (a,b) 都可以凑出。

所以答案就简单了,枚举 i=max(ai),那么 a 的贡献可以直接容斥,就是 (in(i1)n)(ki+1)m,直接算即可。

code


ARC112D *2028

有一个 n×m 的滑雪场,每次可以朝一个方向滑行,如果是冰则直接通过,直到到达一块地面或者撞到边缘停下,现在有一些地方已经是地面,求至少要把多少个冰改成地面可以使一个人从 (1,1) 出发可以到达所有点。

标签:模拟(?

考虑可以到达的点一定是一整行或者一整列的,然后一块地面就是可以从一行走到一列,那么可以直接并查集维护,最后的目标就是覆盖每一行或者每一列,直接找连通块个数即可。

code


ARC126D *2332

有一个长度为 n 的序列,每个元素都 1aik,每次可以交换两个数,问至少多少次操作后满足有一个连续子序列是 {1,2,3...k}

n200,k16

标签:dp。

显然直接状压 dp,如果选了一个数,那么对答案的贡献就是选的数的逆序对个数加上到目标位置的距离,目标位置显然是移动到中位数,直接做就好了。

code


ARC139D *2816

有一个长度为 n 的序列,进行 k 次操作,每次操作随机选择一个 [1,m] 的数加入序列,然后把序列中第 x 小的数删除,求所有方案最后序列中的数之和的和。

n,m,x,k2000

标签:计数。

神题,主要是因为题解看不懂,所以想了很久。

所有数的和可以转化为对于每个 1im,计算有多少个数 i 即可。

开始时先找到 i 的左端点,然后考虑这个左端点的移动,先考虑开始时在 x 右边,那么如果放 [1,i1],那么位置不变,如果放 [i,m],那么就左移动一格,在 x 左边同理。

那么直接枚举左端点最后移动到了哪里,直接计算方案数即可。

code


AGC021D *2287

定义一个字符串 s 的价值是它和它翻转后的串的最长公共子序列,现在已知一个串,进行最多 k 次修改操作,求修改后权值最大是多少。

|s|,k300

标签:dp。

价值的定义显然是最长回文子序列。

所以可以直接区间 dp ,fi,j,k 表示区间 [i,j] 修改 k 次的最大值,直接转移,时间复杂度 O(n3)

code


打了 ABC252,赛时过了 FG,由于是 unr 所以前面的题没做,Ex 想半天不会,寄。

但 psz 赛时不会 FG 我是真没想到。


ABC252G *2153

已知一个先序遍历,如果有多个儿子优先遍历编号小的,求有多少棵树满足这个先序遍历。

n500

标签:dp。

显然直接来,可以发现一个区间要么是一棵树,要么是多棵树,分别开 dp 数组 f,g,直接每次在前面加入一棵树就好了。

code


ABC252Ex *3015

n 个珠子,每个珠子有一个颜色和价值,现在需要每种颜色的珠子各选一个,总价值就是所有珠子价值的异或和,求所有方案总价值第 k 大的价值是多少。

n70,v260

标签:搜索,字典树。

这个 70 有点离谱,因为不知道有啥算法是这个复杂度的。

考虑如果暴力搜索,那么复杂度就是 xi=n,xi 的最大值,根据 powerful number 的相关知识,可以发现这个东西复杂度是 3n3

然后直接 meet in the middle ,分成两部分,复杂度 O(3n6),把一半放到字典树上,然后查询第 k 大。

一个做法是二分,复杂度 3n6log2v 爆炸。

有一个更好的做法,记录每个数在字典树上匹配哪一个节点,然后考虑这一位取什么,然后整体一起移动,这样复杂度 O(3n6)logv

code


bzoj3509

已知一个长度为 n 的数组 a,求有多少对 (i,j,k),i<j<k 满足 ajai=akaj

n105,ai2×104

标签:分块,卷积。

先把式子变一下,变成 2aj=ai+ak,那么考虑枚举 aj,此时相当于找左右有多少个满足条件的,显然可以直接卷积,但复杂度 O(n2logn),不如暴力。

考虑和暴力平衡一下复杂度,考虑分块,对于 i,j,k 都不在一块情况,直接对左右块进行卷积,然后中间统计答案即可。对于至少有一个和 j 在同一块的情况,可以直接开桶暴力算,总时间复杂度 O(n(n+ailogai)),FFT 常数比较大,适当把块长调大即可。


bzoj4403

给定三个正整数 N,L,R,统计长度在 1N 之间,元素大小都在 LR 之间的单调不降序列的数量。输出答案对106+3 取模的结果。

n,l,r109

标签:组合,分治。

首先这个东西显然是一个插板法,考虑把每个数看成一个盒子,然后把数给放进去,可以得到答案是 (RL+NRL),然后相当于一个组合数前缀和,可以发现模数比较小,直接分治就好了。

code


bzoj3057

定义一棵树是好的,当且仅当对于每个节点,它的左右儿子子树深度的差不超过 1。问有多少棵 n 个节点的树是好的。

n3000

标签:dp。

考虑深度的范围,fi 表示深度为 i 的树的最小节点树,gi 表示最大节点树,那么可以发现

fi=fi2+fi1gi=2i1

两个都是 2n 级别的,所以最后的深度是 logn 级别的。

然后直接来,设 fi,j 表示 i 个点,深度为 j 的的方案数,转移的时候枚举左子树大小即可,时间复杂度 O(n2logn)


bzoj4881

已知一个排列,pi 表示 (0,i)(1,pi) 有一条线段,需要把线段分成两个集合,使得这两个集合中的线段两两不交,求方案数,

n105

标签:贪心。

线性做法,已经是 darkbzoj 上的最优解和最短解,目前没有找到另一种线性做法。

其实不是很难,考虑一个暴力做法,如果两条线段有交,那么就把这两条线段连一条边,最后相当于判断二分图方案数,这样暴力复杂度是 O(n2) 的。

考虑对于一个线段区间 [l,r] 没有一条边连向外面,那么可以发现这个区间形成一个独立的二分图,设二分图个数为 m,那么答案就是 2m

现在只剩下判断无解的问题,也就是判断是否可以划分为两个集合,那么从左向右做,相当于两个上升子序列。

这个可以直接贪心,时间复杂度 O(n)

code


bzoj4883

有一个 n×m 的棋盘,要求每行至少放一个白棋,每列至少放一个黑棋,一个格子放棋子有一定代价,求最小代价。

n×m105

标签:并查集。

这种棋盘问题一个经典的结论是考虑建出 n+m 个点然后进行连边,那么可以发现答案一定是一个基环树森林,那么直接贪心并查集维护就好了。

code


bzoj4886

n 张牌,正反面都写着数字,现在可以把这些卡片任意翻转,使得正面的数字两两不同,得分为反面数字之和,求最大得分。

n2×105

标签:贪心。

不错的题。

考虑直接连边,那么可以发现满足条件的联通块一定是树或者是基环树,直接贪心就好了。

code


bzoj4836

定义运算 表示:如果 x<yxy=x+y,否则, xy=xy

已知两个序列 a,b,有 Q 次询问,每次询问一个数 c,问有多少组 aibj=c

所有数据都 50000

标签:卷积。

考虑如果是 ai+bj=c,那么显然是个卷积,但是这里有一个限制条件。

考虑分治,类似分治 fft,每次把 a 中的一个区间和 b 中一个更大的区间卷积,这样就可以了,减法也同理。

时间复杂度 O(nlog2n)

code


CF1220F *2700

已知一个长度为 n 的排列,可以进行若干次循环移位,求多少次移位后得到的序列建出的笛卡尔树深度最小。

n2×105

标签:单调栈,笛卡尔树。

有线段树做法,不过 too hard。

事实上直接来,考虑 1 左边和右边是两个不干扰的部分,因此左边做一下,右边做一下,然后直接合并即可,解决的问题变成加点,查询深度,这个可以在单调栈建笛卡尔树是顺便维护。

code


CF338E *2600

A 有多少长度为 len 的区 间中的数和 B 中的数完美匹配。两个数匹配当且仅当其和不小于 h。 (区间必须连续)

n,len105

标签:线段树。

考虑先把 b 排序,那么可以和 a 中一个数匹配的一定是一段后缀,那么直接后缀加,可以发现满足条件需要满足 aii0,这样双指针和线段树维护即可。

code


CF724E *2900

题比较长,自己看吧。

标签:模拟网络流。

首先有一个网络流的做法就是建 n 个点然后暴力连 n2 条边,直接爆炸,也没什么优化方法。

此时就有一种牛逼的算法:用 dp 模拟网络流。

考虑先变成最小割,然后就相当于要么割上面的,要么割下面的,如果割上面的还需要吧前面连过来的边都割了。

直接 dp,时间复杂度 O(n2)

code


CF722E *2900

有一个 n×m 的网格图,图中有 k 个特殊点。 初始时你有一个权值 s,并且只能向下或向右走, 每经过一个特殊点会使得你的权值/2(向上取整)。 求从 (1,1) 走到 (n,m) 时拥有权值的期望(mod 109+7)。

n,m105,k2000

考虑每次除以 2,最多 logs 次就变成 1 了,所以可以设 fi,j 表示走到第 i 个关键点,经过了 j 个关键点的方案数。

然后直接来,从前面去转移,注意容斥一下就好了。

code


CF1209G2 *3200

题比较长,自己看吧

标签:线段树。

考虑一定是吧序列变成一段段区间,答案就是 n 减去每个区间众数之和, G1 不带修,直接模拟就好了。

考虑用 set 去记录每个数出现的位置,然后区间加,那么相当于 0 的位置就是断点,分开两个连续段。

每个数都直接在左端点放入出现的位置,然后去查询最大值,这样只需要比较左右的最小值就可以判断两区间合并时的情况。

具体而言,如果维护断点复杂度会爆炸,但是可以维护区间最小值,把最小值当做是断点,这样就可以轻松维护了。

code


CF472G *2800

题比较长,自己看吧。

标签:多项式,卷积,分块。

显然这个匹配可以写成一个卷积形式,但是是区间求和,很不好搞。

常见套路是直接分块,块内的和就可以直接维护了,本题需要一定的卡常技巧。

code


CF1553F *2300

已知一个序列 a,定义 pk 表示

pk=i=1kj=1kaimodaj

对于每个 i[1,n],求出 pi

n,ai2×105

标签:树状数组。

考虑递推,那么相当于要计算

(i=1k1akmodai)+(i=1k1aimodak)

右边那个开桶,然后调和级数算,相当于单点加,区间查,直接树状数组。

左边的考虑一个数对后面的贡献,也就是区间加,单点查,也可以树状数组。

code


CF1615G *3300

给定一个数列 a,你需要将所有 ai=0 的位置填上一个 1n 的正整数,使得数列的「值」最大。

数列的值定义为满足以下条件的 kk 的个数:

  • 存在 iZ[1,n1],使得 ai=ai+1=k

输出值最大的序列,若有多解,输出任意一个。

0amin(n,600),0<n3×105

标签:一般图最大匹配。

考虑填数的这些 0 的连续段进行讨论。

如果连续段长度为奇数,那么必然是填 x2 个相同数,然后剩下一个和左右的进行匹配。

如果连续段长度为偶数,那么就有两种情况,要么是填 x2 个相同数,要么左右各匹配一个然后填 x21 个数。

与左右匹配可以看成是一半图最大匹配,先对不同的数值建点。

  • 如果是奇数,新建一个点,向左右的数连边。
  • 如果是偶数,新建两个点,分别向左右连边,然后这两个点连边。

然后直接跑最大匹配,带花树会寄,用随机匹配。

随机匹配也就是把边随机顺序然后跑二分图,不过输出方案比较恶心。

code


CF1615F *2800

对于两个长度为 n01s,t ,你可以对 s 进行两种操作:把相邻两个 0 变成 1 或把相邻两个 1 变成 0 ,定义 st 的距离为最少操作次数使得 s 变成 t ,如过没法变则距离为 0

现在你有两个不完整的字符串,可以把其中的 ? 变成 01 ,求所有情况所得到的两个 01 串的距离之和。

n2000

标签:dp。

不错的题。

考虑把相邻两个相同的翻转很难搞,因为甚至是否有解也判断不了,所以考虑把所有奇数位置上的东西翻转,这样变成翻转相邻两个不同的,也就是交换相邻两个元素。

那么距离就是把所有 1 的位置排序后对应元素差的绝对值了。

考虑 dp 设 fi,j 表示已经做完了 [1,i],前面 s 中的 1 的个数比 tj 个的方案数,那么统计 [i,i+1] 这个部分对答案的贡献,也就是 j×fi,j,转移可以直接转移。

code


ARC102E *2484

nk 面骰子,求对于每个 i ,求出有多少种骰子方案使得没有两个骰子上的数加起来等于 i

n,k2000

标签:组合计数。

考虑对于一个 i ,把所有数分成三类

  • x>i 可以乱选。
  • i 是偶数,x=i2,最多选 1 个。
  • 其他情况,把 x,ix 分成一组,一组中只可以选其中一个。

直接计数即可。

code


打了 ABC253,开局秒了E,然后会了F,psz 给了我 ABCD,F 写了一会儿就过了,发现 G 是 sb 题,类似直接分块然后就好了,但细节很多,psz 去写,我先看 Ex,然后发现会了,找了 10min 矩阵树板子,终于找到了(还不如重写一遍),然后直接冲了一波,WA 了一下,结果发现是没取模。。。然后直接过了。

接下来帮 psz 调 G,然后过了。

第一次 AK ABC,非常开心,总用时 78 分钟。


ABC253Ex *2758

n 个点,m 条边,每次随机加一条边(可以重复加),对于每个 1kn1,求出有多少概率满足加入 k 条边后图是一个森林,答案对 998244353 取模。

n14,m500

标签:矩阵树定理,状压 dp。

考虑枚举森林是怎么样的,然后假设里面有 x 条边,概率就是 x!mx

那么最后的森林是怎么样的呢?直接枚举一个连通块,求出这个连通块是一棵树的方案数,也就是生成树计数,直接矩阵树定理。

然后状压 dp 合并,统计答案即可,时间复杂度 O(n32n+n3n)

code


打 ARC141,晚 50 分钟进场,unr,输麻了。

psz 过 A 之后去看注意开发表重要讲话,笑不活了,直接摆烂。

开局我直接冲 D。

这个 2M 的条件明显是拿来匹配的,然后直接按 2 的幂次分类即可,但是发现寄了。

那就按去掉 2 之后的部分分类,可以发现每一个部分最多选一个,最多有 m 个部分,可以判断无解。

所以就是每个部分选一个,按倍数关系建拓扑图,然后考虑一个点选 2 的幂次。

显然,如果 pq 的幂次,那么 p 乘上 2 的幂次一定小于 q,满足拓扑顺序。

想要满足条件,一个点选的幂次一定是一段区间,正反跑两边拓扑排序即可。

code

观察仔细,你会发现提交时间是 《2022-05-29 22:02:23》,是的,我差 2min 场切 *2800+,悲。


ARC141E *3009

n2 个点,每个点被表示为 (i,j),有 Q 次操作,每次操作把所有 0k<n,将 (ai+k,bi+k)(ci+k,di+k) 连边。

n,Q2×105

标签:并查集。

首先按 ij 把点分类,那么可以发现操作时机上就是两个组中的点对应连边。

如果这两组一开始不是一个连通块,那么直接连通块个数减少 n1

否则,计算这两个联通块的距离,然后相当于求个 gcd 即可。

这些都可以用并查集维护,然后就没了。

code


posted @   houzhiyuan  阅读(152)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示
主题色彩