联合省选 2024
前情提要/kx
D1T1
考虑什么样的 \(m\) 是合法的,发现只需要 \(|X-\sum_{i=0}^{m-1} x_i|+|Y-\sum_{i=0} ^{m-1}y_i|\le mk\)。
这里认为 \(x,y\) 以 \(n\) 为周期无限循环。
把绝对值拆开,可以得到四个式子:
考虑直接枚举最后一个周期停下的具体位置,通过以上四个不等式可以确定周期数的范围 \([l,r]\),将四个范围取交,若为空则这个位置不合法,否则将答案对 \(l\times n+i\) 取 min 即可。时间复杂度 \(O(n)\)。
通过以上推导也可以看出,周期数为 \(O(nV)\) 级别,于是最终的答案为 \(O(n^2V)\) 级别,实际常数大概是 \(3\) 左右,于是可以说明答案一定小于 \(4\times 10^{18}<2^{63}\),全程使用 long long
不会爆。但是 inf 一定要开够!!!
D1T2
把 \(a\) 排序,显然相同的 \(a\) 如果要放到 \(S\) 内一定要一起放进去,于是我们可以先把相同的 \(a\) 合并起来,顺便排序。下面假定序列 \(a\) 严格单调递增。
考虑二分答案 \(mid\),注意到 \(A\oplus B\le A+B\),因此必有 \(a_1+x\ge mid\)(否则 \(a_1\) 一定不合法)。于是 \(x\ge mid-a_1\),进而推出,任何一个数只要放进 \(S\) 中,都一定是合法的。
考虑建出 \(a\) 的 01Trie,然后在 Trie 上 DP:\(f(u)\) 表示 \(u\) 子树内的这些 \(a\) 所需的最小代价,每次决策 \(x\) 的当前位是 \(0\) 还是 \(1\) 即可。这样做一次复杂度为 \(O(nk)\),总复杂度为 \(O(nk^2)\)。
考虑 \(O(nk)\) 咋做。先不考虑集合 \(S\),考虑选一个 \(x\) 最大化 \(\min a_i\oplus x\)。发现可以直接 DP,每次考虑当前位,相当于可以舍弃一边的子树(它们不再对 min 造成约束了),直接走进另一边的子树内接着做。这样复杂度只有一个 \(O(nk)\)。
那现在考虑有集合 \(S\) 了咋办,根据上面的过程我们知道一个数如果放进集合 \(S\) 了一定是合法的。由于我们是在贪心地从高到低确定每一位,因此最优一定是让当前位的 min 尽可能大,为此我们可以选一些子树把它们放进 \(S\) 中来去除它们对 min 的约束;同时还需要 \(x\) 有一个下界。
还是考虑每一位,发现如果当前位上同时有向 \(0\) 走的和向 \(1\) 走的,那么如果没有集合 \(S\),我们这一位上的 min 一定会出现 \(0\),然后我们只需要考虑 \(0\) 这一侧;但有了集合 \(S\) 之后,我们可能的决策就是,把一边的 \(a_i\) 全都放进 \(S\) 中,然后让另一边的 xor 一下,这一位都变成 \(1\),这样就可以把这一位的值变成 \(1\)。
但我们之前还对 \(x\) 有一个下界的约束,发现上面那种情况下如果我们要选一边放进集合 \(S\),讨论一下 \(x\) 的取值:
- 这一位上 \(x\) 取 \(1\),也就是我们把 \(a_i\) 这一位为 \(1\) 的扔进集合 \(S\),这一位为 \(0\) 的接着考虑,发现这里对 \(x\) 没有下界的约束,因为 \(a_i\) 这一位如果是 \(1\),\(x\) 的这一位也是 \(1\),那么加起来直接就 win 了。
- 这一位上 \(x\) 取 \(0\),然后把 \(a_i\) 这一位为 \(0\) 的扔进集合 \(S\),这一位为 \(1\) 的接着考虑。那还是考虑 \(0\) 那边对他的约束,发现只有最小的一个 \(a_i\) 是有用的。我们把这个 \(a_i\) 记录下来,接着往下走。
那这个时候走到一个节点 \(u\) 的时候,对 min 的约束还额外有一个 \(x+a_t\)。考虑决策下一位,发现我们必须要能够进一位,也就是说,这里不能出现 \((x+a_t)_i=0\),直到 \(a_t,x\) 的这一位都取到 \(1\),我们成功进行了一次进位为止。
考虑在 trie 上 DFS,记录 \(\text{solve}(u,w,K,c=0/1,d=0/1)\) 表示当前在结点 \(u\)(也就是说,不在节点 \(u\) 内的 \(a_j\) 都对 \(ans\) 没有约束了),在 \(u\) 往前的部分,\(x\) 和 \(ans\) 都已经确定了的情况下:有一个限制是 ans 对 \(x+w\) 取 min,还剩下 \(K\) 的体力值可以花费,\(c=0/1\) 表示是否钦定后面的位需要传一个进位上来,\(d=0/1\) 表示这里面的元素如果放进 \(S\),是否已经一定都合法了。现在我们同时确定 \(ans\) 和 \(x\) 的当前位,原则是尽量把 \(ans\) 的当前位定为 \(1\)。
然后在 Trie 上进行一些史一样的分类讨论就好了,具体可以看代码。时间复杂度 \(O(nk)\)。
D1T3
你先别急。在写了。
D2T1
先考虑确定 \(Q_1\):二分答案 \(mid\) 然后做一遍 \(O(N)\) 的 DP 即可。这里 \(N=2^n\)。
具体来说 DP 就是设 \(f(u)\) 表示 \(u\) 让子树内决策 \(>mid\) 的最小代价,那么有
其中 \(mn(u)\) 表示 \(u\) 子树内的最小叶子,\(ls,rs\) 分别表示 \(u\) 的左右儿子。
考虑在确定 \(Q_1\) 之后,找到从根到 \(Q_1\) 的链,依次剥出路径边上的 \(O(\log N)\) 个子树,那么可以直接确定 \(Q_2,\{Q_3,Q_4\},\{Q_5,Q_6,Q_7,Q_8\},\cdots\) 等等。这里集合表示内部的顺序尚未确定,但集合之间的顺序是确定的。
我们现在扔掉取到 \(Q_1\) 时做的若干决策,来考虑最小化 \(Q_2,\{Q_3,Q_4\},\{Q_5,Q_6,Q_7,Q_8\},\cdots\) 自己的字典序。发现这些部分之间几乎是独立的。依次考虑每个部分,我们来列一下优先级:
- 首先,\(Q_1\) 需要能取到这个值,因此后面的部分需要预留够足够的 \(K\) 使得它们能够修改一些决策,让子树内能走到的 min 能够 \(>Q_1\)。
- 接下来,这个部分前面的部分由于位置更靠前,优先级理应更高。
设 \(\text{solve}(u,K)\) 为:算出 \(u\) 子树内用不超过 \(K\) 的代价能达到的最优解,以及达到这个最优解所需的最小代价。
我们维护当前剩下的魔力值 \(K\),每次减掉前面用过的和为后面预留的,得到这个子树实际能用的魔力值 \(K'\),递归进当前子树调用 \(\text{solve}(v,K')\) 然后拼接上来即可。有一种情况是,有可能子树内用 \(K'\) 的代价无法让这个子树的最优决策 \(>Q_1\)(也就是说我们在之前 DP 的时候,这里做的决策是直接花费 \(w\) 而非 \(f(rs)\)),我们需要再调用一遍 \(\text{solve}(v,K'-w_{fa(v)})\),然后同理拼接上来。
哎,我场上觉得这个东西简直太没道理了,但是打开 typora 一写又感觉贼对。wuwu
总复杂度大约 \(O(N\log^2N)\)。
D2T2
考虑 \(k=0\) 怎么做:发现是 DAG 拓扑序计数,可以简单做到 \(O(n2^n)\)。
那么 \(k>0\) 相当于把点划分成有序的 \(k+1\) 部分,每部分内部有一个拓扑序的贡献,然后要求这些部分之间不形成环。这里为了方便我们钦定每一部分非空,这样如果划分出了无序的 \(x\) 部分,其方案数还有 \(x!\binom{k+1}{x}\) 的贡献系数。
设 \(f(i,S)\) 表示将点集 \(S\) 划分为 \(i\) 个部分的方案数,转移可以枚举一个部分,钦定它的拓扑序在所有部分之前。 当然啦,这样是会算重的,我们实际上会把一种方案算“它缩点后形成的 DAG 的拓扑序个数”这么多次。
考虑换一种方式统计,每次我们把所有入度为 \(0\) 的点都拎出来,算出 \(g(i,S)\) 表示 \(S\) 分成 \(i\) 部分,且这些部分之间两两没有连边的贡献之和;接下来转移 \(f(i,S)\) 的时候直接把一个极大的 \(T\) 拿出来转移,要求剩下的点中不能有连向 \(T\) 的,转移到 \(f(i-j,S-T)\times g(j,T)\)。
不过呢,这样还是会算重,因为我们只钦定了 \(T\) 是入度为 \(0\) 的点的一个子集。不过这件事倒是很好解决,如果转移用的是 \(g(j,T)\),我们附上容斥系数 \((-1)^{j+1}\),那么由于
我们钦定了非空,所以每个方案恰好算一次。这样复杂度是 \(O(n^23^n)\)。LOJ 能过,洛谷上会 TLE。
注意到瓶颈在最后那个 \(f(i,S)=\sum_{j,T}g(j,T)f(i-j,S-T)\) 的 DP,发现这相当于在第一维做和卷积,第二维做 xor 卷积。设 \(F_S(z)=\sum_{i=0}^nf(i,S)z^i,G_S(z)=\sum_{i=0}^ng(i,S)z^i\),那么转移相当于
带 \(n+1\) 个点值进去,最后 \(O(n^2)\) 插值算出系数即可。这样复杂度就是 \(O(n3^n)\)。