CodeForces
CodeForces
做题记录
-
-
构造题。数学结论:\(11\) 的倍数的奇数位的和与偶数位的和的差的绝对值为 \(11\) 的倍数。
如果 \(2 \mid n\),最后两位为 \(66\) 其他均为 \(33\) 即可,此时满足数学结论。
否则,因为奇数位比偶数位多一位,可以用两位 \(3\) 合成一个 \(6\)。最后四位为 \(6366\),其他均为 \(3\)。代码。
-
构造题。挺好想的。
-
\(n\) 为奇数,答案为 \(n\),最后四位为 \(1, 3, n - 1, n\)。
-
\(n\) 为偶数。设 \(t\) 为 \(n\) 的二进制的长度。答案为\(2^t - 1\)。
-
如果 \(n\) 是 \(2\) 的整数次幂,最后五位为 \(1, 3, n - 2, n - 1, n\)。
-
否则最后三位是 \(n - 2, n - 1, 2^t - 1\)。
-
代码。
-
-
D Yet Another Real Number Problem
考虑前 \(i\) 位时,会把前 \(i\) 项 \(2\) 的次幂和给到一些数,记第 \(k\) 个被给 \(2\) 的数的下标为 \(g_k\)。
记一个区间 \([i, j]\),\(2\) 的次幂的和为 \(t(i, j)\)。
-
对于当前考虑的 \(a_i\),如果 \(a_i \times 2^{t(g_k + 1, i - 1)} \gt a_{g_k}\),令 \(g_k = i\) 。
-
因为 \(a_i \le 1\times 10^9\),故 \(g_{k} - g_{k - 1} \lt 30\),否则令 \(g_{k - 1} = g_k\)。
重复执行上述操作,直到不满足为止。
因为会不断删去前面的 \(g\),最多跳 \(30\) 次,故从左向右执行上述操作的时间复杂度大概为 \(\mathcal{O}(n\log a_i)\)。
删去 \(g\) 可以用单调栈维护。
代码。
-
-
挺有趣的。定义 \(damage(a, b)\) 表示执行 \(a\) 次操作一,\(b\) 次操作二的最大伤害。
贪心地想操作顺序应该是先 \(k\) 次操作一,一次操作二,如是往复。
令 \(c = \min(\frac{a}{k}, b)\),\(damage(a,b) = k\times \dfrac{c(c + 1)}{2}+a\times(b - c)\)。
容易想到 \(damage(a,b)\) 随 \(a\) 或 \(b\) 单调递增,这使我们可以在 \(a\) 或 \(b\) 确认时二分确定 \(b\) 或 \(a\)。
不容易想到 \(damage(a,b)\gt\dfrac{ab}{2}\)。
证明:\(damage(a,b)\) 的最小值在 \(k = 1\) 时取到,因为最后一次是攻击,所以\(a\le b,c = a\)。
\(damage(a,b) = \dfrac{a(a+1)}{2}+a\times(b - a) = a\times(\dfrac{2b-a+1}{2})\gt\dfrac{ab}{2}\)。
可以找到一对 \(a, b\),满足 \(damage(a,b) \gt \dfrac{ab}{2}\ge z\)。此时 \(ab \ge2z\)。
这说明 \(\min(a,b)\le\sqrt{2z}\)。遍历所有 \(a\le\sqrt{2z},b\le\sqrt{2z}\) 时二分计算答案。代码。
时间复杂度为 \(\mathcal{O}(\sqrt{z}\log z)\)。
-
可以说是官解的中文翻译了……
目标是使所有节点的权值变为 \(0\)。
最重要的是想到,如果 \(m\) 次操作可以达到目标,那么 \(2n + m\) 次操作也可行。
证明:在 \(m\) 次操作的基础上先用 \(n\) 次操作将所有节点变为 \(1\),再用 \(n\) 次操作把所有节点都变为 \(0\)。
这说明 \(\forall i \in [0, 2n - 1],x \in\{x|x \bmod 2n = i\}\),\(x\) 次操作对达到目标具有单调性。(后面将证明总是有解的)。
容易得到做法:遍历 \(i\in[0,2n - 1]\),对集合 \(\{x|x \bmod 2n = i\}\) 二分最小的能达到目标的 \(x\)(之后会证明二分的上下界,感性上来讲上界不会太大,上界到 \(1\times10^{13}\) 次可过)。
对于二分的检查函数,可以通过 \(\mathcal{O}(n)\) 的树型 dp 来完成。
- 假设当前的检查的操作数为 \(x\)。\(\mathcal{O}(n)\) 地计算所有节点的操作数,定义节点 \(u\) 的操作数为 \(f_u\)。
- 定义使以 \(u\) 为根节点的子树变为 \(0\) 的额外操作数为 \(h_u\)。使以 \(u\) 为根节点的子树变为 \(0\) 的总操作数为 \(need = \sum\limits_{v \in son(u)} h_v + a_i\)。
- \(need \ge f_u\),\(h_u = need - f_u\)。
- \(need \lt f_u\),必然会有多余的操作,两次多余的操作间可以抵消,所以 \(h_u = (f_u - need) \bmod 2\)。
- 检查 \(h_u\) 是否等于 \(0\),等于 \(0\) 说明操作次数为 \(x\) 可行。
时间复杂度为 \(\mathcal{O}(n^2\log V)\),\(V\) 为二分上界。代码。
本题可以通过确定二分上下界优化成 \(\mathcal{O}(n\log na_i+n^2\log n)\)。同时能证明总是有解。
先解决一个更为简单的问题。使树上所有节点的权值不大于 \(0\) 的最小操作数。与上述树形 dp 的流程大致相同,只是当 \(need \lt f_u\) 时令 \(h_u = 0\)。
可以二分出一个下界 \(t\)。同时对于原问题,\(t\) 次操作后可以令原树的节点的权值全部变为 \(0\) 或 \(1\),原问题的下界肯定不小于 \(t\),这很显然。且上界不大于 \(t + n^2 + 2n + 1\)。接下来仅考虑最坏情况。考虑将所有节点的权值变为同一个数。
- 定义所有节点的权值和的奇偶性为树的奇偶性。每 \(n\) 次操作可以令整棵树的节点翻转。如果每 \(n\) 次操作,除了根节点 \(R\) 以外的节点全部翻转,那么会多出一次操作能用来使另一个节点保持原状,从而改变奇偶性,从而可以接近所有节点权值相同的情况。那么,此处最多为大致 \(n^2\) 次操作。
- 而如果此时 \(R\) 与其他值都不同。可以通过最差 \(n + 1\) 次操作改变:不改变 \(R\),改变一个节点 \(2\) 次。如果全部是 \(1\),再通过 \(n\) 次操作变为 \(0\)。
确定上下界后和原来一样二分就好。
二分区间长为 \((n + 1)^2\),找出 \(t\) 的时间复杂度为 \(\mathcal{O}(n\log (n\max\limits_{i = 1}^{n}(a_i)))\),最后二分的时间复杂度为 \(\mathcal{O}(n\log n^2)\)。总复杂度为 \(\mathcal{O}(n\log (na_i) + n\log n)\)。代码。
-
Educational Codeforces Round 171 (Rated for Div. 2)
-
A Perpendicular Segments 输出边长为 \(\min(x, y)\) 的正方形对角线。代码。
-
只能有一个不属于 \(A\) 的格子可以被涂黑,且被涂黑的格子是两两匹配的。
所以 \(n\) 为奇数时会有一个被断开。\(O(n^2)\) 地检查一遍。代码。
-
C Action Figures 从后往前遍历,如果前面有
0
可以用就用,否则用1
。 代码。 -
将 \(B\) 按起点分类为 \(n\) 类。
对于每一类可以维护其总和,对于每一类内部又维护前缀和。
每次询问可以二分地找到 \(l, r\) 分别属于哪个类。然后容斥地求和。代码。
-
如果 \(a_i\) 的第 \(j\) 位是 \(1\),在 \(a_i\) 和 \(j\) 间建边,这样建了一张二分图。
本题要求的就是二分图最大独立点集。代码。
-
-
-
A Quintomania 检查一遍就好。代码。
-
货架上如果放了某品牌汽水,那么所有该品牌的汽水都可以放。
那么计算某个品牌的所有价值,取总价值前
\(n\) 的的品牌即可。代码
-
C Anya and 1100 一个位置最多对 \(4\) 个子串有影响。检查一遍就好。代码。
-
D I Love 1543 和 C 差不多,暴力检查就好了。代码
-
-
Refact.ai Match 1 (Codeforces Round 985)
-
不跳过时,\([1, i]\) 间最大得分为 \(x\),那么 \([1, i]\) 的得分区间包含 \([0, x]\)。
因为得分变化只有 \(+1, -1\) 或不变。
预处理全部不跳过时的得分情况,并预处理得分的前缀最大值 \(S\)。
-
二分搜索做法。(很神奇的单调性……)
考虑二分最后的答案为 \(k\)。从最后一位向前遍历。
- 假设当前遍历到第 \(i\) 位。
- 如果 \(S_{i - 1} \ge k\),说明可以从前面的某一个位置得到得分等于 \(k\),说明这个得分是可行的。
- 否则向前到第 \(i - 1\) 位,同时令 \(k = \begin{cases}k + 1,&a_{i} < k\\k - 1, &a_{i} \ge k\end{cases}\)(令 \(k\) 尽可能小)。
代码。
-
动态规划做法。
设跳过区间为 \([l, r]\),\(\forall i \in [1, n]\),\(i\) 的所处状态有三种,\(i < l\),或 \(r<i\) 或 \(l \le i \le r\)。
设 \(f_{i, 0/1/2}\) 表示 \(i\) 处于这三种状态时的最大值, \(c(v, x)\) 表示当前得分为 \(v\),\(a_i\) 值为 \(x\) 时的得分。
转移方程式为
\[\begin{cases}f_{i, 0} \leftarrow f_{i - 1, 0} + c(f_{i - 1, 0},a_i)\\f_{i, 1} \leftarrow\max(f_{i - 1, 1}, f_{i - 1, 0})\\ f_{i, 2}\leftarrow\max(c(f_{i - 1, 1}, a_i), c(f_{i - 1, 2}, a_i))\end{cases} \]最后的答案是 \(\max(f_{n, 1}, f_{n, 2})\)。
代码。
-
-
首先可以把图全拆成点或边。
假设每次选择 \(u (d_u \ge 2)\) 和 \(v, w(v, w \in son_u)\) 进行操作。
最后,\(\forall i \in [1, n], d_i \le 1\)。因为每次至少会减少一条边,故操作次数最多为 \(m - 1\) 次。
如果此时 \(\forall i \in [1, n], d_i = 0\),就已经是一张酷图了。输出答案即可。
否则,随便选择一个点为基点,将别的点合并即可。
对于 \(i \in [1, n]\),如果 \(d_i = 0\),那么把它和已经合并好的树上的任一条边和并,原边会消失,而 \(i\) 会与树上两点连边。
对于 \(i \in [1, n]\),如果 \(d_i = 1\),把 \(i, son_i\) 与树上任一点连边。则这条边消失,树上一点与 \(i, son_i\) 连边。
每次至少消失 \(1\) 个孤单的点,故最多进行 \(n - 1\) 次操作。
代码。
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现