杂题乱做2
广二的 NOI round 真不会做(4h=10pts),所以滚回来做些简单题。
「雅礼集训 2018 Day4」Cube
现在三年级都这么厉害了吗?
首先通过打表容易发现答案为 \(\operatorname{C}_n^m*\ 2^{n-m}\),然后快速幂+逆元就过了。
然后就结束了。
证明:考虑建立一个 \(1* 1*...* 1\) 的 \(n\) 维几何体,再考虑建立一个 \(1* 1*...* 1\) 的 \(m\) 维几何体,然后将这个 \(m\) 维几何体放到 \(n\) 维几何体中移动(感性理解一下,比如说平行于 \(z\) 轴的一根线段在正方体上平移到底边的四个顶点),每一个移动的位置就是一个答案。
在 \(n\) 维几何体的 \(n\) 个维度中要有 \(m\) 个维度来确定这一个 \(m\) 维几何体,通过不同的 \(m\) 个维度确定的 \(m\) 维几何体是不同的,比如说一个正方体上有上表面和右表面,两者不是相同的 \(2\) 个维度确定的,前者是通过 \(x\) 轴和 \(y\) 轴相交的平面构成的,后者是通过 \(x\) 轴和 \(z\) 轴相交的平面构成的。
剩下的 \(n-m\) 维每位可以取 \(0\) 或 \(1\) ,共 \(2^{n-m}\) 种,所以答案为 \(\operatorname{C}_n^m*\ 2^{n-m}\)。
ABC264F Monochromatic Path
考虑 dp ,但注意到每一行(或每一列)只能变 \(1\) 次,因此二维 dp 难以实现(例如某一行相邻的两个格子为不同颜色,那么在只变这一行的前提下无法完成),不妨设 \(f[i][j][op_1][op_2]\) 来表示走到 \((i,j)\) 的最小花费,以及第 \(i\) 行和第 \(j\) 列是否变色,若 \(op=1\) 代表已经变色,\(op=0\) 则相反。
那么就有以下转移:(实在不想写 \(\LaTeX\) 了)
now=col[x][y]^op1^op2,last=col[x][y-1]^op1;
if(now==last)f[x][y][op1][op2]=min(f[x][y][op1][op2],f[x][y-1][op1][0]+c[y]*op2);
else f[x][y][op1][op2]=min(f[x][y][op1][op2],f[x][y-1][op1][1]+c[y]*op2);
now=col[x][y]^op1^op2,last=col[x-1][y]^op2;
if(now==last)f[x][y][op1][op2]=min(f[x][y][op1][op2],f[x-1][y][0][op2]+r[x]*op1);
else f[x][y][op1][op2]=min(f[x][y][op1][op2],f[x-1][y][1][op2]+r[x]*op1);
计算代价时一定要注意有没有重复计算!
初值:
memset(f,63,sizeof f);
f[1][1][0][0]=0;
f[1][1][0][1]=c[1];
f[1][1][1][0]=r[1];
f[1][1][1][1]=r[1]+c[1];
答案:\(\max(f[n][m][op_1][op_2])\)
然后就没有然后了,时间复杂度为 \(O(nm)\)。
ABC264Ex Perfect Binary Tree
不要问为什么没有 G,因为 G 还没有改出来。
再一次考虑 dp,可以设 \(f[i][dep]\) 表示以 \(i\) 为根,深度为 \(dep\) 的完美二叉树数量,注意到对于某个父节点的两个儿子都是深度为 \(dep\) 的完美二叉树时,再加上该父节点同样是一棵深度为 \(dep+1\) 的完美二叉树。
每读入一个节点就考虑向根节点更新答案,那么就有转移:
其中 \(u\) 表示当前新增的 \(i\) 号节点所在的那个子树,\(u_{con}\) 表示新增这个节点后这棵子树新增的答案,根据乘法原理和加法原理,容易得出。
然后从 \(i\) 一直往上推即可,记得记一下每个点的父亲。
把 \(u_{con}\) 提出来,剩下的记一下每个节点的孩子 \(f\) 的和再减去 \(f[u]\) 即可。
时间复杂度为 \(O(ndep)\) 不一定能过,但要注意一棵深度为 \(dep\) 完美二叉树有 \(2^{dep}-1\) 个节点,所以 \(dep\le \log n\),在本题中,所有深度大于 \(20\) 的节点都不可能更新答案,所以时间复杂度为 \(O(n\log n)\)。
AGC058A Make it Zigzag
先满足第一个条件,那么此时有:
然后再考虑第二个条件,如果找到 \(P_i<P_{i+1}(i=2,4,6,...)\) 即不满足条件,那么可以直接交换 \(P_i,P_{i+1}\),因为根据之前的第一个条件有 \(P_{i-1}<P_i<P_{i+1}<P_{i+2}(i=2,4,6,...)\),交换后变成 \(P_{i-1}<P_{i+1}>P_i<P_{i+2}(i=2,4,6,...)\) 仍满足第一个条件。
代码两行:
for (int i = 1; i <= n * 2; i += 2) if (a[i] > a[i + 1]) ans[++tot]=i, swap(a[i], a[i + 1]);
for (int i = 2; i <= n * 2; i += 2) if (a[i] < a[i + 1]) ans[++tot]=i, swap(a[i], a[i + 1]);
时间复杂度为 \(O(n)\)。
B 的 dp 没看懂,哪位大佬可以来给我讲讲。。。。
「雅礼集训 2017 Day1」矩阵
首先我们可以得出:如果有某一个点是黑色,一定有解。因为我们可以通过 \(n\) 次复制使得某一行都变成黑色,然后再用 \(n\) 次复制使得所有列变成黑色。
但这样肯定不是最优解,所以在有解的情况下再来一步一步的推:
首先如果有某一行全部是黑色,那么答案就是存在白色的列的个数,因为只有某一行才能去更新某一列,每一个存在白色的列都要某一行去更新,并且每一列更新后不会影响其他列,当不存在白色的列时,这个矩阵都是黑色。
注意此时考虑行是没有意义的,因为只能通过行更新列,无法更新某一行。
但如果没有某一行全部是黑色,我们就要去构造一组全黑的行,因为如果用不是全黑的行去更新会造成更多白点,这些白点之后一定再会被某一个全黑的行来更新,那么之前的更新就是多余的。
不妨枚举某一行,假设考虑第 \(i\) 行,如果第 \(i\) 列存在黑点,那么可以通过将该黑点所在的那一行去更新第 \(i\) 行的每一列,每次可以更新一个白点,更新次数就是第 \(i\) 行白点的数量。
也就是说,假设黑点位置为 \((k,i)\) ,并且 \((i,j)\) 为白点,那么用第 \(k\) 行去更新 \(j\) 列会使得 \((i,j)\) 变成黑点。
如果第 \(i\) 列不存在黑点,那么可以通过这个矩阵上的另一个黑点(如果没有黑点那么一定无解)所在的一行去更新第 \(i\) 列,使其至少有一个黑点,只比上面的操作多了 \(1\) 步。
最后,在构造出全黑的一行后再看看当前白色的列的个数,时间复杂度为 \(O(n^2)\),写代码时一定要注意还原和更新后矩阵的改变。
「雅礼集训 2017 Day1」市场
直接用线段树维护,但操作 \(2\) 无法直接维护,但可以看出最多有 \(\log\) 次操作 \(2\) 区间就会变成 \(1\),所以我们可以直接暴力修改,统计一下区间最大值是否为 \(1\),如果是则直接不修改,这样大概可以拿 \(60\%\) 的分数。
考虑线段树维护的是区间,上面的做法过于浪费,所以观察区间数整除后的变化,将区间和减去变化的数就可以了,但前提是这个区间变化的数相同,才可以用标记记为一个数。
容易发现,如果 \(mx-\lfloor\frac {mx} d\rfloor=mn-\lfloor\frac {mn} d\rfloor\),那么这个区间变化的数都相同(极端情况满足那么中间的情况也肯定满足),这时候直接打标记并且退出即可,不必遍历这个区间。
时间复杂度为 $O( $ 宏学 \()\) ,经过我的观察,极端数据常数大概在 \(100\) 到 \(300\),可以通过。
ABC268F
难度远小于 E,不开 F 真是可惜死了。
容易发现交换两个相邻的字符串对前后的答案没有影响。
所以直接 sort,考虑如何 cmp。
假设相邻的 \(A\) 和 \(B\) 两个字符串,设 \(A\) 中能产生 \(w_A\) 的贡献,有 \(d_A\) 个 X,所有数字和为 \(k_A\),同理设 \(B\) 中能产生 \(w_B\) 的贡献,有 \(d_B\) 个 X,所有数字和为 \(k_B\),那么有:
-
先 \(A\) 再 \(B\):\(w_A+w_B+d_A*k_B\)
-
先 \(B\) 再 \(S\):\(w_A+w_B+d_B*k_A\)
所以比较一下 \(d_A*k_B\) 和 \(d_B*k_A\) 即可。

浙公网安备 33010602011771号