Codeforces Round 1078 (Div. 2) 发表于 2026-02-09 | 更新于 2026-03-30
| 阅读量:
A
贪心。每删除 k − 1 k-1 k − 1 个栅栏必须留下一个。答案为 ⌊ n k ⌋ ( k − 1 ) + n m o d k \lfloor \frac{n}{k}\rfloor(k-1)+n\mod k ⌊ k n ⌋ ( k − 1 ) + n m o d k 。
B
假设我们已经确定了最后把钱放在哪个银行,对于其余的银行 i i i ,除了 a i m o d x a_i \mod x a i m o d x 余下的钱都是可以被转移到最后那个银行去的。枚举即可。
为什么 a i m o d x a_i \mod x a i m o d x 的余数不能被转移?假设我们为了转移这个余数 k k k ,将另外 c 0 c_0 c 0 笔钱移过来,凑好了一些钱,转移了 c 1 c_1 c 1 次到最后的目标银行里。那么这个过程中凑到这个银行里的钱数就是 c 0 ⋅ y + k c_0\cdot y+k c 0 ⋅ y + k ,转出的钱数是 c 1 ⋅ x c_1\cdot x c 1 ⋅ x ,最后对答案的贡献是 c 1 ⋅ y c_1\cdot y c 1 ⋅ y 。如果 c 1 < c 0 c_1<c_0 c 1 < c 0 ,那这个过程是劣的,不如直接把钱转到最后的银行里。而 c 0 ≤ c 1 , y ≤ x , k < x c_0\leq c_1,y\leq x,k<x c 0 ≤ c 1 , y ≤ x , k < x 与 c 0 ⋅ y + k ≥ c 1 ⋅ x c_0\cdot y+k\geq c_1\cdot x c 0 ⋅ y + k ≥ c 1 ⋅ x 矛盾。因此这个结论是正确的。
C
模拟。先预处理 1 0 5 10^5 1 0 5 以内的因数。从小到大枚举答案 l e n len l e n ,枚举成功就退出。令 s i s_i s i 为输入的第 i i i 个字符串。令 S i S_i S i 为 ⋃ j = 1 k { s j , i } \bigcup\limits_{j=1}^{k}\{s_{j,i}\} j = 1 ⋃ k { s j , i } ,即所有 k k k 个字符串在下标 i i i (字符串的下标从 0 0 0 开始)的字符组成的集合。c n t = n l e n cnt=\frac{n}{len} c n t = l e n n 。l e n len l e n 作为答案合法的条件是 ∀ p ∈ [ 0 , l e n ) , ⋂ i m o d l e n = p S i ≠ ∅ \forall p\in [0,len),\bigcap\limits_{i\mod len=p}S_i≠\varnothing ∀ p ∈ [ 0 , l e n ) , i m o d l e n = p ⋂ S i = ∅ 。可以用位运算实现。
D
令被划分到左下部分的位置的和为 w w w ,矩阵的总和为 s s s ,则答案为 w ( s − w ) = − w 2 + s w w(s-w)=-w^2+sw w ( s − w ) = − w 2 + s w ,在 w = ⌊ s 2 ⌋ w=\lfloor\frac{s}{2}\rfloor w = ⌊ 2 s ⌋ 或 ⌈ s 2 ⌉ \lceil\frac{s}{2}\rceil ⌈ 2 s ⌉ 处取到最大值。把这个最优的 w w w 求出来。我们直接从下往上遍历行,一行里从左往右遍历列,找出在哪个位置 ( i , j ) (i,j) ( i , j ) ,第 i i i 行里 j j j 及其左边的和加上第 i + 1 i+1 i + 1 行下面的所有行的和正好是 w w w 。这个位置一定存在。然后模拟输出方案即可。
E
以左上角为起点,右下角为终点 dp 一次,记为 f i , j f_{i,j} f i , j ;以右下角为起点,左上角为终点 dp 一次,记为 g i , j g_{i,j} g i , j 。然后考虑枚举对哪个位置取反。发现此时的答案是可以用 f f f 和 g g g 拼起来表示的。
如果枚举到图里的红色位置,那么不经过红色位置的答案可以用图里蓝色圆圈位置的 f f f 和绿色方框位置的 g g g 拼起来,经过红色位置的答案可以用红色位置的 f f f 和 g g g 叠加,再减去三倍的红色位置的值。处理一下前者的前缀和后缀最大值,再对所有答案取个 min \min min 。需要注意边界。
qq 群里群友教了一个高手的实现:可以不用钦定是否经过跟红色位置在一行的位置,转而钦定经过跟它在一条斜线上的位置。边界情况少很多。
F1
考虑暴力的(有一维是异或和)的 dp 状态 f u , x f_{u,x} f u , x 。它应该代表什么?在某个点 u u u 继承子树状态的时候,我们当然想知道 u u u 所属的连通块目前的异或和是多少,状态里的 x x x 自然就代表这个值。如果 v v v 是 u u u 的儿子,从 f v , y f_{v,y} f v , y 转移到 f u , x f_{u,x} f u , x 的转移自然就分是否断开 ( u , v ) (u,v) ( u , v ) 两种,如果不断开则是 f u , x ← f v , y ⋅ f u , x ⊕ y f_{u,x}\leftarrow f_{v,y}\cdot f_{u,x\oplus y} f u , x ← f v , y ⋅ f u , x ⊕ y ,断开则是 f u , x ← f v , y [ y ∈ b ] ⋅ f u , x f_{u,x}\leftarrow f_{v,y}[y\in b]\cdot f_{u,x} f u , x ← f v , y [ y ∈ b ] ⋅ f u , x 。这个暴力的复杂度是 O ( n V 2 ) \mathcal{O}(nV^2) O ( n V 2 ) 。
发现 k k k 很小,考虑把值域维度优化为与 2 k 2^k 2 k 相关,将直接把值放在状态里换成用集合 b b b 里的元素状态来表示值 ,将复杂度优化到 O ( 4 k n ) \mathcal{O}(4^kn) O ( 4 k n ) 。令 w S = ⨁ i ∈ S b i w_S=\bigoplus\limits_{i\in S}b_i w S = i ∈ S ⨁ b i 。
能否直接用 f u , S f_{u,S} f u , S 表示原来的 f u , w S f_{u,w_S} f u , w S ?我们发现,这样表示的瓶颈在于当一个连通块还没完全形成时,它的异或和并不一定能够被某个 w S w_S w S 表示。
考虑不记录当前连通块的值,而是记录当前所有已经被切掉的子树 的异或和。由于每个被切掉的子树的异或和都属于 b b b ,这些异或和的异或和一定可以被 w S w_S w S 表示!这样我们就得到了正确的状态设计,像暴力那样转移即可。实现时注意有些 S S S 异或出来的结果可能是相同的,需要判一下。