Loading

NOIP模拟赛总结

oiclass #9

T2 染色 II (状压dp,dp优化)

\(x,y\in S\) 则 \((x\operatorname{or} y)\in S\) 说明 \(S\) 对 \(\operatorname{or}\) 运算封闭。

从全集开始考虑。假设 \(2^n-1\) 是蓝色的,考虑找到 \(a\) 中所有的红色位置,记这些位置的或和为 \(S\),考察其具有的性质。注意到位置 \(S\) 一定是红色的,并且所有红色位置必定是 \(S\) 的子集,也就意味着其他位置一定只能是蓝色。这样整个全集就被劈成了两部分,其中外部已经确定了全部都是蓝色的,而内部变成了一个子问题。于是可以设计 \(\mathrm{dp}\)。

令 \(f_{S,0/1}\) 表示考虑 \(S\) 的子集,已经确定位置 \(S\) 的颜色为蓝色/红色的最小价值。\(0/1\) 是对称的,只考虑蓝色。

\(O(2^nn)\) 高维前缀和求出 \(sum_S\) 表示集合 \(S\) 内部的价值和。

\[f_{S,0}=\min_{T\subset S}\set{f_{T,1}+sum_S-sum_T} \]

时间复杂度 \(O(3^n)\),无法通过。考虑优化。

由于枚举子集,我们有 \(|T|<|S|\),我们不一次命中 \(T\),考虑每次只剥离掉一个元素,并在剥离的时候计算上贡献。一定可以找到一个 \(x\in S\) 使得 \(x\in S\wedge x\not\in T\)。令 \(S^\prime=S\setminus \set{x}\),则我们假设 \(T\subseteq S^\prime\)。考虑剥离掉这个 \(x\) 带来的贡献,容易发现就是包含 \(x\) 的那些集合,也就是 \(sum_S-sum_{S^\prime}\) 的贡献。考虑 \(T\) 位置的颜色,如果 \(T\) 正好就是我们想要转移到的那个子集,那么 \(T\) 就应该是红色,否则还没有剥离到最终的子集 \(T\) 就应该是蓝色,因此我们发现 \(T\) 作为蓝色红色都可以,那么转移就是:

\[f_{S,0}=\min_{x\in S}\set{\min(f_{S^\prime,0},f_{S^\prime,1})+sum_S-sum_{S^\prime}} \]

oiclass #10

T4 追忆(树结构,性质分析)

题意就是要求覆盖图中至少 \(i\) 个点所需的最少路径条数。

首先我们选择的路径端点一定都是叶子,否则可以将其扩展到叶子使得覆盖点更多。

考虑 \(i=n\) 的情况。我们熟知,假设树中有 \(l\) 个叶子,那么覆盖所需的最少路径条数为 \(\lceil\frac{l}{2}\rceil\)。

假设我们选择了 \(2l\) 个叶子,考察这些叶子配对之后的 \(l\) 条路径能够覆盖的最多点数。

从叶子出发对整棵树进行拓扑排序,这样可以将树从下到上切开:

对每一层,考虑最底下的 \(2l\) 个叶子能够覆盖这一层的多少点。不难发现,每个点都可以从子树中挑一个叶子出来进行匹配,因此每层都可以覆盖到 \(2l\) 个点。但是这层可能没有那么多点给它覆盖,假设这层有 \(cnt\) 个点,那么能覆盖到的点就是 \(\min(2l,cnt)\)。

因此 \(2l\) 个叶子能够覆盖的最多点数就是 \(S=\sum\limits_{i}\min(2l,cnt_i)\)。对 \(cnt_i\) 排序后扫即可。

时间复杂度 \(O(n\log n)\),使用桶排即可做到 \(O(n)\)。

oiclass #11

T3 奶龙网络(dp,分块)

我们会 \(O(2^knm)\) 的状压做法,这个做法能在 \(k\) 较小时猛猛通过。

有一个类似 meet-in-the-middle 的想法,就是前 \(n-k\) 个暴力枚举状态,后 \(k\) 个用 \(\mathrm{dp}\) 合并,可以做到 \(O(2^\frac{n}{2} \mathrm{poly}(n))\)。受其启发,考虑按 \(k\) 定长分块。马靴说的道理:定长分块可以看成网格图。

在 \(k>16\) 时 \(\lceil n/k\rceil\le 3\),这个网格图最多只有 \(3\) 行。

按列从左到右扫,考虑新增格子 \((r,c)\) 的贡献,发现只有同一行前面的 \(1\)(蓝色)以及下一行前面的 \(1\) 往后的贡献(绿色)。设 \(w_r\) 表示只考虑当前列之前的位置,第 \(r\) 行 \(1\) 的个数和。因此新增贡献是 \(w_r+[r<R]w_{r+1}\)。这样可以设计 \(\mathrm{dp}\),把 \(w_1,w_2,w_3\) 放进状态里,即 \(f(c,w_1,w_2,w_3,s)\) 表示考虑前 \(c\) 列,三行的和分别为 \(w_1,w_2,w_3\),且对数和为 \(s\) 的方案树。时间复杂度 \(O(k^{n/k}km)\)。

oiclass #12

T2 下取整(性质分析,dp 优化)

先按 \(a\) 升序排序。贡献是环状的,不好处理。考虑从最大值 \(a_n\) 的位置断开环,从 \(a_n\) 后面的位置开始走,这样可以直接消除掉 \(\lfloor\frac{B_1}{B_n}\rfloor\)。这样操作一定不劣,因此最优解中 \(B_n=a_n\),断环成链。

类比找到 \(a_1\) 的位置,可以发现 \(a_1\) 之前一定是递减的。现在只考虑 \(a_1\to a_n\) 的部分。容易发现这部分一定是递增的,否则可以把凹下去的部分扔到左边拼起来。现在唯一能造成贡献的就是 \(a_1\sim a_n\) 递增部分带来的贡献。

直接设计 \(\mathrm{dp}\) 令 \(f_i\) 表示以 \(a_i\) 结尾的贡献最小值。不难得到转移:\(f_i=\min\limits_{j<i} \set{f_j+\lfloor\frac{A_i}{A_j}\rfloor}\)。

有一万种方法优化,比较简单的就是先去掉下取整,转化成 \(\lfloor f_j+\frac{A_i}{A_j}\rfloor\),然后斜率优化就行了。

T4 救护车(背包 dp,贪心)

有点过于神秘了。

先令 \(T\leftarrow \lfloor\frac{T}{2}\rfloor\)。问题可以被转化成:有 \(4\) 个容量为 \(T\) 的背包,要把 \(n\) 个物品放进去,每个物品放到不同背包中贡献不同的重量,问能不能做到。于是就可以设计一个 \(O(nT^4)\) 的可行性背包,可以进一步将状态设计为前三个背包已用容量固定时第四个背包已用容量的最小值,从而做到 \(O(nT^3)\),直接优化比较困难。

考虑弱化问题,弱化成只有两个对角的医院,以 \((1,1)(L,L)\) 为例,对于位置 \((x_i,y_i)\):

  • 放到 \((1,1)\) 的代价是 \(a_i=(x_i+y_i-2)\)。
  • 放到 \((L,L)\) 的代价是 \(b_i=(2L-x_i-y_i)\)。

可以发现对于同一个点,其到两个医院的代价之和 \(a_i+b_i=2(L-1)\) 为一个定值,这意味着 \(a_i\) 越大 \(b_i\) 越小,因此按照 \(a_i\),也就是 \((x_i+y_i)\) 升序排序后,最优解一定是一段前缀给 \((1,1)\),后缀给 \((L,L)\)。对 \((1,L)(L,1)\) 也是同理,按 \((x_i-y_i)\) 升序排序后一定是一段前缀给 \((1,L)\) 一段后缀给 \((L,1)\)。于是弱化的问题得到了解决,现在考虑拓展到 \(4\) 个角。

我们注意到 \(2\) 个对角的结论可以扩展到 \(4\) 个角,对 \((1,1)(L,L)\) 而言,就是按照 \((x_i+y_i)\) 排序后,一定存在分界点 \(p\) 使得 \(p\) 之前的点全部选择 \((1,1)\),后面的点全部选择 \((L,L)\),同理按 \((x_i-y_i)\) 排序后一定存在 \(q\) 使得 \(q\) 之前全部选择 \((1,L)\),之后全部选择 \((L,1)\)。

考虑直接枚举分界点 \(p,q\),这样可以把所有点分成四类:按 \((x_i+y_i)\) 排序后在 \(p\) 左边还是右边;按 \((x_i-y_i)\) 排序后在 \(q\) 左边还是右边。这样每一类内部的点只有两个医院可以选。于是就可以用之前的 dp 了,对于每一类,令 \(f_{i,a,b}\) 表示考虑前 \(i\) 个物品,第一个医院已用容量为 \(a\),第二个医院已用容量为 \(b\) 是否可行,优化为 \(f_{i,j}\) 表示第一个医院已用容量为 \(j\) 时第二个医院已用容量的最小值。转移为:

\[f_{i,j}=\min(f_{i-1,j-u_i},f_{i-1,j}+v_i) \]

这样背包单次的时间复杂度 \(O(nT)\)。令 \(f_0,f_1,f_2,f_3\) 分别表示 \((1,1)(1,L)\),\((1,1)(L,1)\),\((L,L)(1,L)\),\((L,L)(L,1)\) 的结果。

枚举 \((1,1)\) 在第一类中用的容量 \(W_0\),和第二类中用的容量 \(W_1\)。那么 \((1,L)\) 最少用 \(t_{(1,L)}=f_0(W_0)\),\((L,1)\) 最少用 \(t_{(L,1)}=f_1(W_1)\)。第三类会给 \((L,L)\) 贡献 \(f_2(t_{(1,L)})\),第四类会给 \((L,L)\) 贡献 \(f_3(t_{(L,1)})\),那么我们判断是否有 \(t_{(1,L)}\le T,t_{(L,1)}\le T,f_2(t_{(1,L)})+f_3(t_{(L,1)})\le T\) 即可知道这种方案是否可行。可以预处理前缀 min 省去 \(W_1\) 的枚举,于是这样的时间复杂度为 \(O(nT^3)\),无法通过。

考虑优化,按照 \((x_i-y_i)\) 排序扫描 \(q\) 的时候 \((1,L)(L,1)\) 只决定于 \(i\le q,i>q\),而 \((1,1)(L,L)\) 只决定于 \(rk_i\le p,rk_i>q\),其中 \(rk_i\) 表示按照 \((x_i+y_i)\) 排序后 \(i\) 的排名。因此只需要对前后缀分别跑一个背包,然后在 \(q\) 处拼接即可。这样时间复杂度为 \(O(n^2T)\),可以通过。

仙人掌(三)

100+65+100+20=285,rk9,不会 T2。

T2 绅士 gentleman(数位 dp)

考虑一个比较有启发性的暴力:注意到由于 \(\mathrm{Big}(A)\le 9\),取模之后最多变成个位数,因此暴力把 \(A\) 跑到 \(<M\) 的最大数,然后处理取模,这样最多 \(10\) 次之后由抽屉原理一定会出现循环。

注意到这个可以拓展,如果一次进位到了第 \(k\) 位,那么除了个位以外的更低位一定都是 \(0\),呈现一个 \((+1)000\dots 0x\) 的形态,把这个设计成 \(\mathrm{dp}\),令 \(f_{k,d,x}\) 表示考虑低 \(k\) 位,第 \(k\) 位及以上的最大数为 \(d\),更低位呈现 \(000\dots 0x\) 的形态,此时要使第 \(k+1\) 位发生进位所需要的步数,另外记 \(to_{k,d,x}\) 表示跳到的个位数。

然后就可以从低位往高位拓展,每次尝试将当前位进行进位,并判断能不能跑满。这样可以快速计算 \(F(A,N)\) 表示数 \(A\) 经过 \(N\) 步之后跳到的数,然后再套用上述不断跳 \(<M\) 的做法即可。

仙人掌(四)

T1 卡牌游戏 card(二分)

气笑了。考虑转化一下题意,变成分组使得开头和结尾相同,形如 \(\texttt{(ABC)(CBA)(ACB)\dots}\),假设分了 \(k\) 组,这样实际得分就是组数 \(k\),实际使用卡片数为 \(3k-(k-1)=2k+1\),每组恰好含一个 \(A,B,C\),因此至少使用的卡片数为 \(\min(A,k)+\min(B,k)+\min(C,k)\),直接二分即可。

posted @ 2026-09-26 11:12  STDJCY  阅读(3)  评论(0)    收藏  举报