2021.12.11 互测

北校哥哥们出的互测题。

又是写完暴力就不知道干些什么了。

T1

人老了,已经不会写这么精致的 DP 了。

首先将 \(a\) 排列固定为 \(1,2,\dots n\),DP \(b\) 排列的方案数,最后乘 \(n!\)

发现每填一个数,代价取决于较大数,也就是从前往后放,数字 \(i\)\(1\dots i\) 位置放时计算一下代价;而前面哪些位置能放,只关心合法位置的数量。

DP 设 \(f(i,j,k)\) 表示前 \(i\) 个数中有 \(j\) 个数已经确定了位置,代价和为 \(k\)。枚举数字 \(i+1\) 是不动、往前放、往后放,再枚举位置 \(i+1\) 是小数填、大数填,分 5 种情况转移。

复杂度 \(\mathcal O(n^2m)\)

T2

先建 kruskal 重构树,每次询问二分答案,再在树上倍增算出覆盖点数,\(\mathcal O(q\log^2 n)\)

哦还可以整体二分,用可撤销的并查集。复杂度不变,但是并查集那个 \(\log\) 要小得多。

T3

zx 怎么搬 Ynoi 啊。

第一感觉应当是区间长度 \(\mathrm{len}\) 越大越可能有解。根据鸽巢原理,权值和至多为 \(v\times \mathrm{len}\)\(1024\times\mathrm{len}<2^{\mathrm{len}}-1\) 解得 \(l\) 最大为 \(13\)。也就是说长度 \(>13\) 的询问一定有解。

\(\mathrm{len}\le 13\) 的问题考虑暴力,只需要枚举子集求和,用桶统计。这样就保证是不交的了,因为权值相同的两个集合不可能是包含关系,有交集的话两者都减去交集便是合法解。

或者也可以 \(\texttt{std::bitset<>}\) 优化背包。

实际上阈值设为 \(9\) 都能过的。

T4

学傻了,这点性质都看不出来。

所有数肯定是先 \(\bmod 2\)。尝试枚举行集合,如果这些行异或起来全为 \(0\),那么不能存在合法的列集合;否则 \(2^m\) 种列集合方案中有一半的集合是合法的。

那么要求行异或起来不为 \(0\) 的方案数。反过来求行异或起来为 \(0\) 的方案数,考虑先建立线性基,线性基外任何一个集合的异或和,都可以被线性基的一个子集表示。设线性基大小 \(c\),那么方案数就是 \(2^n-2^{n-c}\)

需要用 \(\texttt{std::bitset<>}\) 优化一下,复杂度 \(\mathcal O\left(\frac{nm^2}{\omega}\right)\)

posted @ 2021-12-11 15:42  RenaMoe  阅读(62)  评论(1编辑  收藏  举报