概况
5 题, 共 4h,我 1,dry 4。
A - X 魔法对
预期:AC,实际:AC。
题意
给定 \(a,b,x\) 三个正整数,可以做若干次操作,每次操作可以把 \(a\) 或者 \(b\) 改为 \(|a-b|\),问能否做若干次操作,使 \(a\) 或 \(b\) 变成 \(x\)。
思路
暴力超时,考虑数学。
令 \(a>b\),则发现把 \(b\) 变成 \(|a-b|\) 是无效操作,因此会把 \(a\) 变为 \(|a-b|\)。又发现,在出现 \(a<b\) 前,会一直执行上述操作,所以考虑一步到位,将 \(a\) 变为 \(a \bmod b\),然后交换 \(a,b\),循环上述操作。
在操作过程中(直到出现 \(0\)),出现 \(a-k\times b=x\), \(a=x\) 或者 \(b=x\),那么有解,否则无解。
B - “或”游戏
预期:AC,实际:WA。
题意
给定长度为 \(n\) 的正整数序列 \(a_i\),和正整数 \(x,k\),可以给任意的 \(a_i\) 一共乘上 \(k\) 个 \(x\),最大化序列的或和。
思路
容易发现乘法操作要一起做,且做在尽量大的数上,考虑给某个数乘上 \(k\) 个 \(x\)。在二进制位的层面上,位数最高的数乘出来位数一样的,由于或运算的特性,最终的或和会补充低位的空缺,于是不能确定在某个数上做乘法一定或和最大,为了方便,枚举每个数来乘 \(k\) 个 \(x\),求最大值,具体实现可以用前、后缀或和来辅助处理。
为什么没做对?
想到给最大的数做乘法,但怕错,就写了个 DP,表面看起来很对,但或运算是不满足最优子结构的,也就是说这一步的最优不一定能用到下一步的最优中去。
所以在 DP 时要想清楚问题要求什么,为什么要用 DP,DP 不是万能的。
C - 离散离心跳跃
期望:TLE,实际:TLE。
题意
一排 \(n\) 个房子,高度为 \(a_i\),从房子 \(1\) 跳到 \(n\),从 \(j\) 跳到 \(i\) 需满足条件之一:
- \(i=j+1\)
- \(\max (a_{j+1},a_{j+2}...a_{i-1})<\min(a_i,a_j)\)
- \(\min (a_{j+1},a_{j+2}...a_{i-1})>\max(a_i,a_j)\)
求最小步数。
思路
DP。
条件 1 好转移,考虑 2。
对于 \(i\),求在 \(i\) 前面,离 \(i\) 最近的大于等于它的数 \(j\),则 \(j+1\sim i-1\) 都可以转移。维护一个单调下降的单调栈,在弹出时转移即可,手推。
3 与 2 类似,也是单调栈。
为什么没做对?
看了眼题就不太会,没怎么思考。
多注意单调栈、单调队列优化 DP 的条件。
D -表格游戏
期望:AC,实际:WA。
题意
给定 \(n\) 行 \(m\) 列的矩阵,若干次操作:删一整行或整列,问能否使矩阵的和为 \(s\),要输出方案。
思路
数据范围是 \(1\le n,m\le 15\),考虑搜索,时间复杂度是 \(O(2^{n^2})\),于是可以用 meet in the middle,折半搜索,优化为 \(O(2^{\frac{3}{2}n}n)\)。具体实现是先枚举行的删除情况,然后枚举一半的列的删除情况,再枚举另一半列的删除情况,用 map 来找匹配的一半即可。
为什么没做对?
想 DP,结果我的 DP 可以乱删,子矩阵不一定代表父矩阵。
要注意数据范围,搜索也有可能是正解(虽然有卡常)。
E - 恢复排列
期望:WA,实际:WA。
题意
定义排列 \(a_i\) 的 \(s\) 数组:\(s_i\) 表示在 \(a_i\) 前面且小于 \(a_i\) 的数的和。给定一个排列 \(a_i\) 的 \(s_i\),构造出 \(a_i\)。
思路
观察样例,考虑 \(0\) 表示什么,即前面没有比它小的数,如果有多个 \(0\),那么最后一个 \(0\) 一定可以填最小的数,所以考虑 \(n\) 轮,第 \(i\) 轮找到最靠后的 \(0\),把它设为 \(i\),再把它后面的数减 \(i\)。用线段树可以完成。
为什么没做对?
如何构造是想到了的,但不会实现,这是真不应该。
多练。