2024.04 做题笔记
- CF1903F
考虑二分答案,现在问题变为求是否有一个覆盖集,选出的点两两编号差 \(\ge k\)。
不难想到 2-SAT,那么有两类限制;一类是对于一条边,两端中至少选择一个;另一类是对于编号差 \(<k\) 的点,两者至多选择一个。用线段树优化建图即可。
- ARC096E
考虑容斥,每钦定一个出现了 \(\le 1\) 的数,乘上一个 \(-1\) 的权值。
现在需要计算 \(f(i)\) 表示至少出现 \(i\) 个违反条件的数的方案数。首先钦定 \(i\) 个,方案数为 \(\binom{n}{i}\),其次乘上其他 \(n-i\) 个数任意选的方案,为 \(2^{2^{n-i}}\)。现在还需要解决部分包含 \(i\) 个数中一些的集合。
枚举 \(j\),表示这些数分进 \(j\) 个集合,那么会有一个 \(2^{j(n-i)}\),表示每个集合对应的另一侧的 \(n-i\) 个都可以任选,还会有一个第二类斯特林数的系数。
时间复杂度 \(\mathcal O(n^2)\),需要预处理各种幂,注意 \(2^{2^{n-i}}\) 要欧拉定理。
- CF1942F
很 CNOI 的题。
那个以 \(\log \log V\) 为块长分块,建立线段树在线维护的做法有点麻烦,我来个简单做法。
首先观察到所有结果全部下取整不影响答案。
我们考虑离线做扫描线。正常的以时间轴为扫描轴,以序列轴为数据结构维护轴的做法显然不可行,我们大胆把两者交换,也就是以序列轴为扫描轴,用数据结构维护每个时间点经过一个前缀序列之后得到的结果。
把问询塞到对应的序列位置上,从左到右扫描序列。那么每个操作影响到的范围是时间轴上的一段区间。现在问题转化为 \(\mathcal O(n+q)\) 次区间加,\(\mathcal O(n)\) 次区间开根。
用线段树维护,考虑如何均摊。对于每个节点,记录对应区间的最大值和最小值。区间加正常做,区间开根可以不断递归直到 \(mx-\lfloor\sqrt{mx}\rfloor=mn-\lfloor\sqrt{mn}\rfloor\),这时候对于这个节点只需要区间减 \(mx-\lfloor\sqrt{mx}\rfloor\) 即可,容易分析出复杂度为 \(\mathcal O(n\log n\log \log V)\)。
- CF1613F
起手一个容斥先拍上去,考虑钦定一些点的点权和 \(fa\) 相同,发现这样被钦定的点集一定形成若干条链。假设钦定了 \(k\) 个点,剩下的点方案数为 \((n-k)!\),对于已经被钦定的点,已经被确定了,因为链顶已经被确定,那么一条链就直接推出来了。
现在问题转化为如何计算大小为 \(i\) 的点集组成若干条直链的方案数,对于每个点,都可以选择一个儿子,或者结束这条链,那么方案数的 OGF 为 \((1+d_ix)\),其中 \(d_i\) 表示 \(i\) 的儿子数量,我们也可以把容斥那步直接融进去,即求 \((1-d_ix)\)。可以分治 NTT,做到 \(\mathcal O(n\log ^2 n)\)。还有一个高妙的做法:从高次到低次直接依次乘起来,复杂度是正确的 \(\mathcal O(n\log n)\)。
- P10064
首先考虑合法条件:对于任意两个叶子节点能走到的点集 \(T_x,T_y\),都满足 \(T_x\cup T_y\neq \emptyset\)。不难证明这等价于所有的 \(T_x\) 的并集不为空。
容易发现 \(T_x\) 为一个连通块,所以这里采用一种很巧妙的容斥:点减边容斥,具体而言,考虑对于点计算这个点在 \(T_x\) 的并集中的方案数,减去对于每条边的两端在 \(T_x\) 的并集中的方案数,不难发现每个有效连通块恰好被算了一次。我们考虑如何计算点的答案,边的答案是类似。
现在的主要问题出在 \(x\to y\) 的路径如果经过 \(u\),且两端都是叶子时,计算会出现问题。我们考虑进一步容斥!即设 \(f_{i}\) 为出现了 \(i\) 个满足 \(u\notin T_x\) 的 \(x\) 的方案数,这样就可以背包 dp 了,时间复杂度 \(\mathcal O(n^3)\)。
这时候我们发现最后到父亲那个子树再做容斥太蠢了,可以直接枚举内部叶子数量计算,时间复杂度 \(\mathcal O(n^2)\)。
很巧妙,技巧性很强的计数题。希望自己隔段时间再回来看看加深印象。
- AGC039F
最优解,取之!!!
做法一:考虑设 \(x_i\) 为行内最小值,\(y_j\) 为行内最小值,那么权值即为 \(\prod\min(x_i,y_j)\)。可以考虑按照大小顺序加入计算,这也导向了我们的做法。考虑容斥,即整体上从小到大加入,转移的时候枚举 \(r,c\),钦定 \(r\) 行 \(c\) 的对应位置比当前枚举到的值更大。这样得到一个 \(\mathcal O(n^5)\) 的做法,但是我们发现两维的转移是独立的,可以使用 trick 分步转移,即先转移行的容斥,再转移列的容斥,复杂度为 \(\mathcal O(n^4)\)。
做法二:这个太高了,很难想到。考虑 product trick,即另开一个矩阵 \(B\),在 \(B_{i,j}\) 处填上一个不超过 \(f(i,j)\) 的正整数,那么 \(A\) 的权值就是合法的 \(B\) 的数量。考虑合法的 \(B\) 的条件:\(B\) 的每行最大值都 $\le $ 这行 \(A\) 的最小值,\(B\) 的每列最大值都 $\le $ 这列 \(A\) 的最小值。那么就可以设 \(f_{i,j,k}\) 为 \([1,i]\) 的值,已经确定 \(B\) 中 \(j\) 行最大值,\(A\) 中 \(k\) 列最小值的方案数。转移也是可以分步进行的,复杂度 \(\mathcal O(n^4)\)。
两个做法都需要合理的预处理,不然会多出一个 log。
浙公网安备 33010602011771号