集训总结(二)
9.3
P4001 狼抓兔子
平面图转对偶图板子题。转换方式如下:
1.对于图中的每个网格,将其看成一个点;
2.对于两个相邻的点,将其连边,边权为相隔线段的边权;
3.对于网格边缘的点,建立两个虚点 \(S\),\(T\),左方、下方的点向 \(S\) 连边,右方、上方的点向 \(T\) 连边。
跑一遍 \(S\) 到 \(T\) 的 dij 即可。
P2831 愤怒的小鸟
一道搜索剪枝的好题 虽然正解是状压dp
搜索的思路很好想。
枚举每个猪,判断它是否在之前的抛物线上,如果在,直接继续往下搜;
否则分两种情况:空闲或和之前空闲的猪组成一条抛物线。
答案即为抛物线数量+空闲猪的数量。
最后加上最优性剪枝:若此时抛物线数量+空闲猪数量 \(\ge\) 先前搜索到的最优解,直接返回。
注意精度问题。
P13953 原根
洛谷重现赛场切了,纪念一下。
首先,将式子转化一下:\(g \oplus(P-1)\equiv1(mod\) \(P)\) \(\to\) \(g=(kP+1)\oplus(P-1)\)。
由异或性质可得:异或最大值等于两数相加,异或最小值等于两数差的绝对值,因此可以表示出 \(g\) 的范围:\((k-1)P+2 \le g \le (k+1)P\)。
根据这个式子,我们还能发现一些性质:当 \(k \le \frac{m}{P}-1\) 时,一定符合条件;当 \(k \ge \frac{m-2}{P}+1\) 时,\(k\) 一定不符合条件。
发现 \(k\) 在它们之间的范围很小,直接枚举即可。
9.4
P4138 挂饰
背包dp。
首先,对所有挂件按挂饰数量从小到大排序。设 \(f_{i,j}\) 表示考虑到第 \(i\) 个挂件,此时挂饰有 \(j\) 个的最小代价。初始 \(f_{0,1}=0\)。
转移很简单: \(f_{i,j}=min(f_{i,j},f_{i-1,max(j-v_i,0)+1}+w_i)\)。
P3960 列队
发现每次操作,会改变操作所在行和最后一列,所以我们对每一行开一棵线段树,再对最后一列开一棵线段树,题目中的操作就相当于单点修改,单点查询。空间可能开不下,所以要动态开点。
P3959 宝藏
个人认为是一道很好的状压 dp 题。
注意到 \(n\) 的范围很小,很自然地想到状压。
观察可以发现:最后拓展出的藏宝室和开始赞助商确定的藏宝室构成一棵树。
证明:若最后形成了一个环,由于边权一定为正,所以我们可以去掉环上任意一点,形成的解均比环优。
考虑如何 dp。一个很自然的想法是枚举每个赞助商确定的藏宝室,将这个点作为树根,然后不断加入新边并更新答案。
考虑新加入边 \((u,v)\) 对答案的影响。与贡献代价有关的条件有两种:树的深度与边 \((u,v)\) 的长度 \(w(u,v)\)。设连接深度为 \(x\) 和 \(x+1\) 的边集为 \(S\),则总贡献为 $$x*\sum_{(u,v) \in S} w(u,v)$$
思考状压 dp 的过程,发现可以将深度相同的节点作为一个集合,于是我们便可以设计 dp 了。
设 \(f_{i,S}\) 表示树深度为 \(i\),树中的点集为 \(S\) 的最小代价。设计状态转移方程为:
其中 \(dis(S,T)\) 表示最小的能连通 \(S\) 和 \(T\) 中的点的最小代价。
转移的时候出现了一个问题:如何保证 \(T\) 中的节点都连接到第 \(i\) 层?
感谢大蛇 C_Escape_Obsession 的解答:若 \(T\) 中的节点并未全部连接到第 \(i\) 层,则转移时它们的最优决策点应在第 \(i\) 层之前,而我们此时是在第 \(i\) 层进行转移,这样会导致它们的贡献偏大,所以一定不优,所以在转移时一定不会将它们作为最优决策点。
知道了大致思路,代码就很好写了。预处理出 \(dis\) ,借助子集枚举,可以做到 \(O(n^23^n)\)。
9.5
P10237 E. Latent Kindom
虽然官解是二分,但 zb 看到空间这么大,直接写了权值线段树。
对每个序列开权值线段树,查询时将两个序列权值线段树的查询合并即可。记得离散化。
P3166 数三角形
很容易想到答案为:任选三个格点的方案 \(-\) 三点共线的方案。
任选三个格点的方案很好想,为 \(C_{(n+1)(m+1)}^3\)。三点共线分三种:横线、竖线、斜线。
前两种很简单,分别是 \((n+1)*C_{m+1}^3\) 和 \((m+1)*C_{n+1}^3\),主要是第三种。
结论:两个横坐标相差 \(i\),纵坐标相差 \(j\) 的点之间的格点数为 \(gcd(i,j)-1\),证明略。
大小为 \((n+1)(m+1)\) 的平面答案即为 \(2*\sum_{i=1}^n \sum_{j=1}^m (n-i+1)(m-j+1)*(gcd(i,j)-1)\)
直接 \(O(n^2logn)\) 计算即可。