CF 做题记录(2026.4-5)

CF2217D. Flip the Bit (Hard Version)

\(x\)\(0\)\(\lnot x\)\(1\)

翻转 \(\longrightarrow\) 异或

区间异或 \(\longrightarrow\) 差分

两两配对,如果有主元素,不能两两配对,操作次数为每段 max

否则可以两两配对,为总数 \(S / 2\)

注意到两个关键点之间 \(1\) 的端点数一定为偶数(一定都是完整的段,每段两个端点),只有最后一个关键点到结尾可能出现不完整的段,导致端点数为奇数,需要补一个点

CF2205G. Simons and Diophantus Equation

条件等价于 \(\gcd(i \oplus j, j \oplus k) \mid n\)

那么计算

\[\begin{aligned} \sum_{x | n} \sum_{i, j, k} \left[ \gcd(i \oplus j, j\oplus k) = x \right] \end{aligned} \]

利用莫反(注意当 \(i \oplus j = j \oplus k = 0 \Leftrightarrow i = j = k\) 时不能莫反)

\[\sum_{x | n} \sum_{d} \mu(d) \left( \sum_{i, j, k} [dx | i \oplus j \land dx | j \oplus k] - (m + 1) \right) \]

枚举乘积,令 \(p = dx\),得

\[\sum_{p} \sum_{x | n \land x | p} \mu\left(\frac{p}{x}\right) \left( \sum_{i, j, k} [p | i \oplus j \land p | j \oplus k] - (m + 1) \right) = \sum_{p} g(p) \left( \sum_{i, j, k} [p | i \oplus j \land p | j \oplus k] - (m + 1) \right) \]

其中 \(g(p)\) 可以 \(O(m \ln m)\) 求出

考虑后面的求和式,可以拆开,并枚举 \(p\) 的倍数,变成

\[\sum_{j} \left( \sum_{i} [p | i \oplus j] \right)^2 = \sum_{j} \left( \sum_{k} [kp \oplus j \le m] \right)^2 \]

\(\le m\) 的条件可以通过 Trie 维护,在 Trie 树上可以标记满足条件的子树,但是平方的出现导致贡献非常难算,我们需要把标记全部下传,我最多只能做到 \(O(m^2\log m)\)

由于单次查找中被标记的点是 \(O(\log m)\) 的,总共只会有 \(O(\frac{m}{p} \log m)\) 个标记,所以我们考虑如何避免下传

考虑把贡献拆到每个标记上,如果点 \(u\) 被标记(注意一个点可以被多次标记),那么存在一个 \(k\) 使得所有在 \(u\) 子树内结尾的数字 \(j\),有 \([kp \oplus j \le m]\),那么我们可以考虑两个标记,记他们所对应的 \(k\)\(k_1, k_2\),他们所标记的子树交集就是 \([k_1 \oplus j \le m]\)\([k_2 \oplus j \le m]\)\(j\) 个数,那么就可以统计进答案里,所以,对于 Trie 上的一个节点 \(u\) 处的标记,它的贡献是

\[\sum_{v \in A_u} f_u + \sum_{v \in T_u} f_v \]

\(A_u\)\(u\) 的祖先链(不含 \(u\)),\(T_u\)\(u\) 的子树,\(f_u\) 表示在 \(u\) 子树内结尾的数字个数

\(O(m \ln m \log m)\)

这个拆贡献的思想与题解中 \(+1\) 再求和的做法是类似的,如法炮制,我们也可以拓展到三次方的情况,拆贡献的时候考虑 \(3\) 个标记即可

CF2192E. Swap to Rearrange

首先刻画条件,考虑两边同一个数字的个数,\(A_x, B_x\) 分别表示 \(x\)\(a, b\) 中的出现次数,那么最终要使所有 \(A_x - B_x = 0\),令 \(f(x) = A_x - B_x\),容易发现交换 \(a_i, b_i\) 会使 \(f(a_i) \leftarrow f(a_i) - 2\)\(f(b_i) \leftarrow f(b_i) + 2\),所以有解的必要条件是 \(A_x - B_x\) 是偶数,然后我们审视这个问题,似乎可以流,考虑建图,从 \(a_i\)\(b_i\) 连一条有向边,容易得到一个网络流做法

但是网络流太慢了,我们想点别的

考虑我们刚刚是怎么建图的,从 \(a_i\)\(b_i\) 连一条有向边,那么交换实际上就相当于改变边的方向,最后使得每个点入度等于出度,跑欧拉回路即可,一条边如果被反向走就说明两个数被交换了

posted @ 2026-04-20 19:52  zhm0725  阅读(14)  评论(0)    收藏  举报