「2023/02」学习记录
这次只写了部分题(包括 1 月写的非 WC 题)。模拟赛题均没写。有亿点小鸽。
这篇甚至能叫 CF 杂题乱做()。
快省选了,看看怎么调整可以提升最大吧。
「CF57E」Chess
一个无限大的棋盘里,有 \(n\) 个点 \((x_i,y_i)\) 被删除,计算国际象棋中的骑士能够在 \(k\) 步内到达的不同的格子的数目。
保证 \(k \le 10^{18}\),\(n \le 440\),\(|x_i|,|y_i| \le 10\)。
先不考虑被删的点。无所谓,我会打表(。我们把走到第 \(i\) 步的点的数量打出来。
然后发现他挺有规律的,做个差分。
7 24 36 28 24 28 28 28 28 28 28 28 28 28 28
然后发现,\(x,y\) 坐标都非常小。通过画图可以发现,经过一定数量后,这些被删除的点不会影响后续的变换了。
那么这题做法就很清晰了,先暴搜若干步,然后剩下的用等差数列算。
「CF79D」Password
你有 \(n\) 个灯泡,一开始都未点亮。同时你有 \(l\) 个长度,分别为 \(a_1 \sim a_l\)。
每次你可以选择一段连续的子序列,且长度为某个 \(a_i\),并将这些灯泡的明灭状态取反。
求最少的操作次数,使得最后有且仅有 \(k\) 个位置是亮的,这些位置已经给定,为 \(x_1 \sim x_k\)。
保证 \(n \le 10^4\),\(k \le 10\),\(l \le 100\)。
先对整个序列做一个差分。于是每次操作变成了修改 \(b_{l-1},b_{r}\) 的权值。
而每次操作最多产生 \(2\) 个 \(1\),也就是最多 \(2k\) 个 \(1\)。所以直接状压,两个状态之间的花费可以预处理。预处理类似最短路。
「CF274E」Mirror Room
有一个 \(n\times m\) 的格子图,其中有一些是黑色的,另一些为白色。
从某个白色格子的中心点向左上(NW),左下(SW),右上(NE),右下(SE)四个方向中的一个发出一束光线,若光线碰到黑色格子或者墙壁(即边界)会反射。反射情况如图所示:
我们不难发现,光线能穿过的格子总数是可以算出的。假如光线经过了某个格子的中心,则称光线经过了这个格子。求光线经过的格子总数。
性质题。
激光最后一定会循环,而且是 \(\mathcal{O}(n+m+k)\) 级别的,并且不会穿过同一个格子的两个对角线。
然后暴力做就好了。
「CF626F」Group Projects
有 \(n\) 个学生,每个学生有一个能力值 \(a_i\)。现在要把这些学生分成一些(任意数量的)组,每一组的“不和谐度”是该组能力值最大的学生与能力值最小的学生的能力值的差。求所有不和谐度之和不超过 \(k\) 的分组方案总数。
保证 \(n \le 200\),\(k \le 1000\),\(a_i \le 500\)。
看成数轴上的若干个点,每组的贡献相当于所有点连起来的长度。
排序,不妨设 \(f(i,j,k)\) 表示前 \(i\) 个点,有 \(j\) 条线段的右端点尚未确定,不和谐值为 \(k\) 的方案数。分类讨论转移即可。
这样状态数比较大,考虑将 \(a\) 差分,令 \(t = (a_{i+1} - a_i)\cdot j\) 来转移。
「CF626G」Raffles
有 \(n\) 个奖池,第 \(i\) 个奖池的奖金是 \(p_i\),已经有 \(l_i\) 张彩票押在上面。
现在你有 \(t\) 张彩票,你需要将你的彩票分配到这些奖池中,并且保证你在每个奖池中押的彩票数不能超过该奖池原有的彩票数。
若你在第 \(i\) 个奖池中押了 \(t_i\) 张彩票,则你中奖的概率为 \(\frac{t_i}{t_i + l_i}\),若你中奖,你可以获得这个奖池的全部奖金 \(p_i\)。
一共有 \(q\) 次事件,每次事件会使某个 \(l_i\) 加 \(1\) 或减 \(1\)。你需要在每个事件后求出在最佳方案下你获得的奖金总数的最大期望值。
保证 \(n,t,q \le 2 \times 10^5\),\(p_i,l_i \le 10^3\),答案精度误差 \(\le 10^{-6}\)。
考虑一个已经放了 \(c_i\) 个彩票的池子加一个彩票的贡献:
可以发现贡献是递减的。
于是我们可以开一个堆,里面放所有池子加一的贡献,每次取出最大值再存入该池子的新贡献,即可完成不带修的版本。
修改一个池子的 \(l_i\) 时,可能就会出现选了一个不优(非最大值)加入池子。考虑找出贡献最小的点,然后回溯回去找到更大的贡献。
这样复杂度是对的。每次修改只会修改 \(1,-1\)。每次只会修改一张彩票。
把堆替换成 multiset
即可。
复杂度 \(\mathcal{O}((n+t+q) \log n)\)。
「CF936D」World of Tank
有一个 \(2 \times n\) 的格子,有一个坦克,初始在 \((0,1)\)。每秒会向右移动一格,同时你可以选择向上或者向下(先向右再切换行)。
另外,坦克有安装炮弹,初始以及每次打完有 \(t\) 的冷却时间,可以打碎当前所在行向右最近的一个障碍。
问是否能到达最后一列,如果可以,输出方案。
如果只有一行,我们肯定有炮就开是最优的。每次有炮就开一定不劣。
但每次开炮不好记录摧毁障碍,改成遇到障碍才开开炮,但是冷却时间按一有就开的来算。
然后考虑 DP。设 \(f(i,j)\) 表示到 \((i,j)\) 位置的最大留下的时间。复杂度 \(\mathcal{O}(n)\)。
「CF1012E」Cycle sort
给定一个长为 \(n\) 的数组 \(a\)。
你可以进行若干次操作。每次操作给出 \(k\) 的不同的下标 \(i_1, i_2, \ldots, i_k\),然后将这些下标的元素进行顺时针轮换。即:\(a_1\to a'_2, a_2\to a'_3, \ldots, a_{k-1}\to a'_k, a_k \to a'_1\)。
现在要求所有操作的 \(k\) 的总和不超过 \(s\) 的前提下,操作数的最小值。无解输出
-1
。保证 \(n \le 2 \times 10^5\)。
先考虑排列的情况。我们不妨连边 \(i \rightarrow p_i\) 然后就得到了若干个环。分别操作是不够优的,我们考虑一次操作一个大小为 \(k\) 的环,把 \(k\) 个环合并。
我们需要的最少合并次数为 \(\sum\limits_{i=1}^n [p_i \not=i]\)。假设环有 \(m\) 个,那么最小操作次数就为 \(m-\min(m,s-(\sum[p_i \not = i]))+2\)。
如果不是排列,我们依然先排序成 \(b_i\),连边 \(a_i \rightarrow b_i\)。然后发现入度和出度都相等,于是每个连通块都存在一个欧拉回路。我们跑出欧拉回路,然后把它当成环就可以了。
「CF1028H」Make Square
我们称一个数列 \(b\) 是“优秀的”,当且仅当存在 \(b_i\times b_j(i<j)\) 是一个完全平方数。
给定一个数列 \(a\),每次询问使 \(a_l,a_{l+1},\cdots,a_{r-1},a_r\) 这个数列成为一个“优秀的”数列至少要进行几次操作,共\(q\)次询问。
每一次操作,你可以将数列中的任意一个数乘以/除以一个质数 \(p\)(除法需要保证被除数能被整除)。
保证 \(2 \le n \le 194598\),\(q \le 1049658\),\(1 \le a_i \le 5032107\)。
如果把每个数质因数分解,我们就只需要考虑一个质因数的次幂的奇偶性。不妨直接对 \(2\) 取膜。
那么对于两个数 \(x,y\) 的操作数就是两边指数只有 \(1\) 个位 \(1\) 的个数。如果我们设 \(f(x)\) 表示 \(x\) 分解后指数为奇数的质因子个数,那么 \(x,y\) 的答案就是 \(f(x)+f(y) - f(\gcd(x,y))\)。
而一个数最多有 \(7\) 个不同的质数,可以直接维护。
枚举 \(\gcd\) 后扫描线维护就行了。
「CF1067D」Computer Game
有 \(n\) 个游戏,每个游戏有收益 \(a_i\),升级后的收益 \(b_i\),每次成功概率 \(p_i\)。每秒可以玩一个游戏,如果成功则得到当前收益,并且可以升级任意某个游戏。求 \(t\) 秒后的期望收益的最大值。
保证 \(n≤10^5\),\(t≤10^{10}\),\(a<b\)。
升级成功后肯定每次选最大的 \(b_ip_i\)。成功前考虑 DP。不妨设 \(f(t)\) 表示剩下 \(t\) 秒且尚未升级成功,每次枚举一个游戏当前玩。设 \(v=\max\{b_ip_i\}\)。于是有转移:
考虑优化这个式子。我们把里面拆开。
可以表示为 \(kx+b\) 的形式。令 \(k=p_i,b=p_ia_i,x=v\cdot(t-1)-f(t-1)\)。
于是可以考虑斜率优化了。先求出下凸壳,然后转移每次二分找出 \(x\) 在凸壳上哪条直线上就行了。
但是 \(t\) 非常大,不能直接转移。
考虑 \(vt-f(t)\) 这个东西。因为有 \(a<b\),所以一定有 \(0 \le f(t)-f(t-1) \le v\),于是有 \(f(t) \le f(t-1) +v\),最后得出了 \(vt-f(t) \ge v(t-1) - f(t-1)\)。这意味着 \(x\) 是单调不降的。
那我们直接在凸包上扫,一条直线上的可以直接一起转移,用矩阵优化:
直接倍增即可。复杂度 \(\mathcal{O} ( n \log n)\)。
「CF1081G」Mergesort Strikes Back
一个长度为 \(n\) 的随机排列,进行深度为 \(k\) 的归并排序(\([1\dots n]\) 为第一层),求期望逆序对个数。答案对一个素数取模。
保证 \(n,k\leq 10^5\),\(10^8\leq mod\leq 10^9\)。
考虑每次合并两个序列的贡献。对于一个序列,我们做一个前缀最大值,然后被他分成若干个块,一个块内一定满足第一个数大于块内的其他数,且大于他前面的数。
所以我们做归并的时候,对于两个块,如果一个块的开头更小,那么紧接着,这个块中的所有数都会按顺序全部归并进去。
不妨设最底层的长度为 \(x\),每对数都有一半的概率贡献一个逆序对,于是有贡献 \(\dfrac{x(x-1)}{4}\)。而根据之前分析的,之后都是块开头合并,所以这层的数之后相对顺序都不会改变。
考虑两个序列合并,不妨设分别是第 \(i\) 个数和第 \(j\) 个数,他们的块头也就是前缀最大值。如果这两个块头的最大值是 \(i,j\) 之一,那么他一定不会贡献逆序对。否则他们有一半的概率贡献,期望 \(\dfrac{1}{2} \cdot \dfrac{i+j-2}{i+j} = \dfrac{1}{2} - \dfrac{1}{i+j}\)。
可以预处理所有 \(i\) 的 \(j\) 的贡献。
复杂度 \(\mathcal{O}(n \log n)\)。
「CF1214H」Tiles Placement
给出一个 \(n\) 个点的树,给出颜色种类数 \(k\),现在要给每一个点染色,每一个点只能染一种颜色.
求一种染色方案,使得树上任意一条点数为 \(k\) 的简单路径包含 \(k\) 种颜色,若没有输出
No
,若存在第一行输出Yes
,第二行输出 \(n\) 个整数,第 \(i\) 个数字表示 \(i\) 号点的颜色。保证 \(2 \le k \le n \le 2 \times 10^5\)。
先考虑什么时候无解。
可以发现,如果存在 \(3\) 个点他们之间的距离均 \(>k\),一定无解。对于 \(k=2\) 直接一层一层染色就可以了,特判掉。
剩余情况一定有解。
我们先找出一个直径,对于非直径上的点,如果他到直径两端的距离均 \(> k\),就是无解的情况了。
考虑怎么染色。选择直径的中点为根,然后一层一层染就可以了。
「CF1254E」Send Tree to Charlie
给出一棵 \(N\) 个节点的树,初始时第 \(i\) 个节点上有一个数字 \(i\)。
每次你可以选择一条未被删除的边,交换这条边连接的两个点上的数字后,删除这条边。
现给定一个序列 \(a\),第 \(i\) 个位置上若不为 \(0\),则代表要求最终第 \(i\) 个位置上的数要为 \(a_i\)。否则没有特殊要求。
试求出,执行 \(N-1\) 次操作之后,有多少种最终局面满足序列 \(a\) 的要求。答案对 \(10^9+7\) 取模。
保证 \(2 \leq N \leq 5 \times 10^5\),\(0 \leq a_i \leq N\)。
你说得对,但是树上的数。
如果 \(a\) 序列都为 \(0\),我们考虑答案是多少。可以发现,一个点所连出的边的顺序如果定下来了,那么这个点最后的权值也定下来了。所以答案就是 \(\prod \text{deg}(u)\)。
接下来考虑,如果 \(a_u = x\),我们应该怎么移动。首先 \(a_u = u\) 一定无解。然后对于点 \(u\),他最后选择的边应该是在 \(u \rightarrow x\) 上的边。而 \(x\) 第一个选择的边也应该是在这上面的边。而在 \(x \rightarrow u\) 的链上的点,面向 \(x\) 的边删掉后,下一个必须删面向 \(u\) 的点。
如果两个条件冲突,或者限制成环,那么一定无解。
然后直接每个点统计一遍答案就可以了。
「CF1284F」New Year and Social Network
给定两棵大小为 \(n(n\le 2.5\times 10^5)\) 的树 \(T_1,T_2\)。
若你删去 \(T_1\) 上的一条边 \(i\) 后,可以选择 \(T_2\) 上的一条边 \(j\) 连接上来而形成树,则称 \((i,j)\) 是匹配的。
对于树 \(T_1\) 的一条边,你需要为其标记一个数字/不标记,你标记的数字不能相同,你标记的数字 \(x\) 与此边所构成的二元组 \((i,x)\) 是匹配的时候,你才能以数字 \(x\) 标记其。
求你最多能标记多少条边。
由于 CF 给的样例没有无解所以一定有解。
这个条件相当于,删掉一条边 \(i\) 后,\(j\) 两个点在 \(i\) 中不属于同一个连通块。
我们不妨设一个边集 \(S\),把他全部割掉后,求出 \(T_2\) 中两端不属于同一个连通块的边的数量。我们将一个连通块染成一个颜色,于是答案为 \(n-1\) 减去同色边的数量,于是对于一个颜色 \(c\),我们设他连通块大小为 \(f_c\),然后显然有 \(\sum f(c) = n-1 - |S|\) 。
这意味着,同色边的数量是不超过 \(n-1 - |S|\) 的。根据 Hall 定理,我们可以发现这一定有最大匹配。
然后我们希望这个问题可以递归解决。
我们选 \(T_1\) 的一条边,然后在 \(T_2\) 上把这两个端点合并。然后我们希望在 \(T_2\) 上删除一条边,可以匹配,且删除后 \(T_2\) 仍然是一棵树。
那我们每次选取一个 \(T_2\) 的叶子边 \((u,v)\),在 \(T_1\) 上选择在路径 \(u \rightarrow v\) 上并且与 \(u\) 相连的边即可。
递归做,用并查集维护。
「CF1517F」Reunion
给定一棵 \(n\) 个点树,点要么为黑点要么为白点。定义一次合法的聚会为,选择一个点 \(x\),所有与点 \(x\) 距离不超过 \(r\) 的点均为白点。一个合法聚会的等级为所有可能 \(r\) 中的最大值。
现在每个点有等概率为黑白点,求出所有情况下,聚会等级的期望和。特殊的,如果有点均为黑点,那么等级为 \(-1\)。答案对 \(998244353\) 取膜。
保证 \(n \le 300\)。
求所有情况的 \(r\) 的和,考虑直接转化为对于所有 \(d \in [1,n)\),求出所有 \(r \ge d\) 的方案数,的总和。
对于一个 \(d\),我们定义如果两个点 \(\operatorname{dis}(u,v) \le d\) 那么 \(u,v\) 是相互约束的。所以我们要求存在一个点 \(u\),他约束的点均为白点的方案数。
考虑反过来计算 \(r<d\) 的方案数,这意味着一个点 \(u\) 的约束点至少有一个是黑点。
考虑 DP。我们需要记录点 \(u\) 子树中,如果子树内都被覆盖,那么离 \(u\) 向上的最浅的覆盖的点;如果都没覆盖,那么最深的没有被覆盖的点。这两个显然不会同时存在。设 \(f(u,i)\) 表示在点 \(u\) 子树中,如果 \(i\ge 0\) 表示前者,\(i<0\) 表示后者。
直接转移是 \(\mathcal{O}(n^4)\) 的,考虑如何优化。注意到对于一个 \(u\),他的有效状态(\(\not=0\))是有 \(sz_u\) 种,用一个 vector
啥的维护一下就可以了。复杂度 \(\mathcal{O}(n^3)\)。
「CF1572D」Bridge Club
有 \(2^n\) 个点从 \(0\) 到 \(2^n-1\) 编号,每个点有点权,两个编号为 \(u,v\) 的点之间有边当且仅当 \(u\) 和 \(v\) 有且仅有一个二进制位不相同。要求从这个图中选一个最多 \(k\) 条边的匹配,使得被匹配所包含的 \(2k\) 个点点权和最大,输出这个最大点权和。
保证 \(1 \le n \le 20\),\(1 \le k \le 200\)。
因为只有相差 \(1\) 个不同的才会连边,所以把二进制下 \(1\) 个数为奇数的为一边,偶数为另一边,然后就是二分图了。
可以发现一个点连出去的点数恰好为 \(n\)。那么我们每匹配 \(2\) 个点,都会最多使答案少去 \(2(n-1)\) 个匹配,即这两个点的连出去的剩下的 \(2(n-1)\) 个点都没有匹配。
这意味着我们每匹配一次就会减少 \(2n-1\) 次。匹配 \(k\) 次就会最多减少 \(k(2n-1)\) 个,反过来,匹配 \(k(2n-1)\) 个他也就有 \(k\) 种匹配方式。
那我们令每个匹配的权值为两个点的权值和,直接选取权值最大的 \(k(2n-1)\) 种匹配,他一定存在 \(k\) 种匹配。
「CF1656H」Equal LCM Subsets
有两个集合 \(A,B\),大小分别为 \(n,m\),你需要找两个非空子集 \(S_A\subseteq A,S_B\subseteq B\),使得 \(S_A\) 中的元素的最小公倍数和 \(S_B\) 中的元素的最小公倍数相等。若无解,输出
NO
,有解输出YES
和任意一组解。多组数据,数据组数 \(t\leq200,1\leq \sum n,\sum m\leq1000,1\leq a_i,b_i\leq4\times10^{36}\)。
首先每个数可以质因数分解,形如 \(a_i = \prod p_i^{v_i}\)。于是 \(\operatorname{lcm}\) 就是所有质因子的次幂最大值。
我们将相等的条件拆成两部分。\(\operatorname{lcm}(S_A) | \operatorname{lcm}(S_B)\) 和 \(\operatorname{lcm}(S_B) | \operatorname{lcm}(S_A)\)。下面就讨论一种。
对于 \(\forall p_i, \forall x \in S_A, \exists y \in S_B\) 都有 \(v_p(x) \le v_p (y)\)。但因为值域太大,没法直接分解出所有质因数。所以我们换一种表达,即 \(v_p(x) - \min(v_p(x),v_p(y))=0\)。
幂次取 \(\min\),可以发现这就是 \(\gcd\) 的形式。于是 \(v_p \left( \frac{x}{\gcd(x,y)} \right) =0\)。
考虑把 $\exists y \in S_B $ 也改成取 \(\min\) 操作。于是有 \(v_p \left( \gcd\limits_{y \in S_B} \{ \frac{x}{\gcd(x,y)} \} \right)\)。
考虑一个暴力,先把所有数都塞进两个集合。然后暴力判断每个元素,如果不满足上面那个式子,直接删掉。
如果最后出现了一个空集,就是无解。
枚举过程似乎不太好优化掉,那么考虑计算过程。我们不妨开 \(n+m\) 个线段树,维护单点修改,即删掉一个数就是改成 \(0\),区间查 \(\gcd\)。
复杂度 \(\mathcal{O}(nm(\log n + \log m + \log w))\)。
「CF1764G」Doremy's Perfect DS Class
这是一道交互题。
交互库有一个 \([1,n]\) 的排列 \(p\)。你可以询问 \(l,r,k\),交互库会返回 \(\left\lfloor\dfrac{p_l}k\right\rfloor,\left\lfloor\dfrac{p_{l+1}}k\right\rfloor,\cdots,\left\lfloor\dfrac{p_r}k\right\rfloor\) 中不同数的个数。
你需要在 \(20\) 次询问内找到 \(p\) 中 \(1\) 的位置。
满足 \(n\in[3,1024]\)。
考虑二分。当我们取 \(k=2\) 时,\(2x\) 和 \(2x+1\) 的结果就是一样的。如果 \(n\) 为奇数,那么意味着除了 \(1\) 其他数字都有 \(2\) 个。于是其他数字对 \(\text{query}(1,x,2)\) 与 \(\text{query}(x+1,n,2)\) 的贡献是一样的。这意味着 \(1\) 在贡献多 \(1\) 的那边。直接二分即可。
如果 \(n\) 为偶数。那么如果 \(n\) 和 \(1\) 不在同一侧,两边的数量就一致,无法判断 \(1\) 在哪边。
当然我们可以选择开头就找出 \(n\) 的位置,取 \(k=n\) 然后二分即可。这样需要 \(20+10 = 30\) 次。
不妨将这个二分和后面判断 \(1\) 的过程合并。如果出现相同再判断 \(n\) 在哪边。然后舍弃另一半即可。需要 \(20+1 = 21\) 次。
最后一次二分考虑优化掉一个询问。
此时我们已经知道了 \(\text{query}(1,l-1,2),\text{query}(1,r,2),\text{query}(l,n,2),\text{query}(r+1,n,2)\)。而 \(l,l+1\) 这两个位置中不是 \(1\) 的那个数,和左还是和右配对是可以通过上述计算出的。最后只需要 \(20\) 次询问。
「CF1767F」Two Subtrees
给你一棵有根树,每次给出两个子树(可能有交),求这两个子树中所有的点权的最小众数。如果一个点被两个子树覆盖算两次。
满足 \(n,q,v_i \le 2 \times 10^5\)。
处理出 dfs 序。每次相当于给出两个区间问众数。
直接进行一个四维的莫队。出现次数可以再开一个值域数组记录。
复杂度 \(\mathcal{O}(n^{\frac{7}{4}})\)。
「CF1774F」Magician and Pigs
你现在有一个空序列,需要维护如下三个操作:
- \(1\ x\):在序列中添加 \(x\)。
- \(2\ x\):把序列中每个元素的值减去 \(x\)。
- \(3\):重复从第一条到本条操作的前一条的所有操作。包括操作 \(3\)。
当一个数的值小于等于 \(0\) 时,它将被移出序列。请输出最后有多少个数还在序列中。答案对\(998244353\) 取模。
保证 \(n \le 8 \times 10^5\),\(1 \le x \le 10^9\)。
如果不考虑 \(3\) 操作。我们只需要额外记录一个标记 \(cnt\),表示所有数都要减去 \(cnt\)。那如果加入一个新的数 \(x\),我们只需要将新数改成 \(x+cnt\) 就行了。
而每经过一次操作 \(3\),\(cnt\) 就会 \(\times 2\)。所以对于一个数 \(x\),他最多经历 \(\log x\) 次操作就被移出了。
于是问题变成了,有若干个数 \(w_i\),每次可以选或者不选,求选出来的总和 \(\le x\) 的方案数。并且满足 \(w_i\) 至少是前一个数的两倍。所以可以直接看成 \(w_i\) 进制,一位一位算即可。