跳转至

2021-2022 BUAA XCPC Team Supplementary Training 03

排名 当场过题数 至今过题数 总题数
3/20 8 12 12

B

solved by 2sozx Bazoka13

题意

给定一个二分图 \(A, B\),集合大小分别为 \(n, m\),每个点有权值,一个点集使可以被选择当且仅当在原图中存在一个匹配,使得选择的点集中的所有点都是这个匹配的端点,并且点集的权值和大于 \(t\)。问有多少种选择点集的方式。\(1\le n, m\le 20, t\le 10^9\)

题解

根据 Hall 定理,我们可以分别预处理出来 \(A,B\) 的子集使得其能成为一个匹配的端点,并且预处理出来每个子集的权值和。

如果子集 \(S_A,S_B\) 分别是 \(A,B\) 中的可行子集,那么 \(S_A \cup S_B\) 一定是原图中可以被选择的子集。证明放在最后。因此我们可以将所有 \(B\) 的可行子集按权值和大小排序,对于每个 \(A\) 的可行子集二分查找即可,注意此题选择可以为空际。

简略证明:

考虑 \(A\) 的可行子集,\(B\) 同理。

对于一个可行子集 \(S\) ,所对应的 \(B\) 中子集为 \(T\) ,我们可以知道对于此时的 \(S\) 以及原图的任意一个匹配包含 \(S\) ,则 \(S\) 所连的点一定包含了一个必选子集 \(H\),而且我们可以推断出与 \(H\) 所连的点集 \(G\)。从 \(S,T\) 中刨除 \(G, H\) 得到 \(S^{'}, T^{'}\) 。如果 \(T^{'}\)\(S^{'}\) 中还有必选子集 \(H^{'}\) ,我们进行讨论。

  • 如果 \(H^{'} \cap G = \varnothing\) 显然把这个删除,剩余的在原图中一定可以找到一个匹配
  • 否则设 \(H^{'}\cap G = I\),我们会发现 \(I\) 对应了一个原来在 \(S\) 中必选的 \(H\) 以及非必选的 \(H^{'}\)\(H\cap H^{'} = \varnothing\) ,这样根据我们对于必选的定义,会发现原先的选择 \(G\) 并非必选,与假设矛盾,因此不存在这样的情况。

证毕。

D

upsolved by 2sozx JJLeo

题意

\(6\times 6\) 的矩阵,\((1, 1)\) 开始存有 \(n\) 个无序的数,按照堆排列,并且没有相等的元素。每次操作可以选择一个位置 \((x, y)\) ,从顶部取走连续的一段放入 \((x+1, y)\) 或者 \((x, y+1)\) 的栈顶,问一种操作方式使得最终到达 \((6, 6)\) 的时候从栈底到栈顶是递增数列。(\(1 \le n \le 40000\))

题解

我们考虑简单的情况。\((1,1)\) 只可以排好一个数, \((1, 2),(2,1)\) 的位置最多可以将两个数排成递增或递减数列,而对于其余的 \((x,y)\) 会发现将 \(1 \le i \le x, 1\le j \le y\) 其与所有位置 \((i, j)\) 按照能排列好的数最多去放置,这样对于到 \((x, y)\) 的排序方法即为多路归并排序,因此我们可以知道每个 \((x, y)\) 最多能排好多少个数。

递推式为 \(f(x,y) = \sum \limits _{i=1}^x \sum \limits _{j=1}^y[i \ne x \lor j \ne y]f(i,j)\),特别地 \(f(1,1)=1,f(1,2)=f(2,1)=2\)

\(f(6,6)=42960\)

对于将初始状态排序好,可以从 \((6, 6)\) 开始贪心的排序,尽量将其余的状态放满数即可。由于这个排序每次会将原来的顺序取反,因此递归时需要考虑此时需要递增数列还是递减数列。

对于 \((1, 2),(2, 1)\) 位置且要放置 \(2\) 个数时我们需要特判,因为这两个数都是从 \((1, 1)\) 转移过来,但是是要进行两次操作的,因此与其余方式不同。

递归可以写成 vector<int> solve(int i, int j, int n, bool d) 的形式,表示需要在 \((i,j)\) 这个位置上面出现 \(n\) 个升序 / 降序的数 (和 \(d\) 有关),返回这些数组成的 vector<int>

E

solved by JJLeo Bazoka13

题意

找到 \(n\) 个满足 \(a^2 + b^2 + c^2 = k(ab + ac + bc) + 1\) 的三元组 \((a, b, c)\) ,并且方案中 \(a, b, c\) 最多只出现一次,答案每个数位数不超过 \(100\)\(n, k\le 1000\)

题解

找到一组初始解 \(a = 1, b = k, c = k + k ^ 2\) ,考虑固定两个数,我们可以得到一个方程组。

\[ \begin{cases}a_1^2 + b^2 + c^2 = k(a_1b + a_1c + bc) + 1\newline a_2^2 + b^2 + c^2 = k(a_2b + a_2c + bc) + 1 \end{cases} \]

两式相减化简可得

\[ (a_1 - a_2)(a_1 + a_2 - k(b + c)) = 0 \]

由于 \(a_1 \not = a_2\) ,则有 \(a_2 = k(b + c) - a_1\) ,根据特解寻找即可。

G

upsolved by JJLeo Bazoka13 2sozx?

题意

\(2^n \times 2^n\) 的网格图,每个位置上数字都不同,范围是 \(\left[0,2^{2n}\right)\)。递归地给每个格子标号,从高到底依次确定二进制下每一位:

  1. 首先把当前区域竖直地分成面积相等的两半,\(x\) 坐标大的那一侧这一位是 \(1\)\(x\) 坐标小的那一侧这一位是 \(0\)
  2. 再把当前区域水平地分成面积相等的两半,\(y\) 坐标大的那一侧下一位是 \(1\)\(y\) 坐标小的那一侧下一位是 \(0\)
  3. 这样就确定了两位,把当前区域分为了四个面积一样的区域,继续递归这四个部分,确定每部分更低的位。

一共递归进行 \(n\) 轮,这样 \(2n\) 位上的数字都确定了。

现在给出一个 \(m\) 个顶点的简单多边形,保证所有边都是竖直或者水平的且贴着格子边界,设这个多边形内部包含的数字组成集合是 \(S\)

现在有 \(q\) 组询问,每次给定一个值 \(k\),你需要选择至多 \(k\) 个区间,设使得这些区间的并是 \(T\),要求 \(S \subseteq T\),最小化所选区间的长度之和。

(\(1 \le n \le 30\)\(4 \le m \le 200\)\(1 \le q \le 10^5\)\(1 \le k \le 10^9\))

题解

首先,假设我们求出了多边形内部包含的的数,把他放到数轴上,如果 \(k=1\),答案就是最大值减去最小值;否则,其内部一定有很多空隙,\(k\) 每增大 \(1\),就可以去掉一个空隙,因此只需减去最大的 \(k-1\) 个空隙即可。

我们考虑如何求出这些空隙。

一个最暴力的做法就是模拟上述递归过程,假设此时值域是 \([l,r]\),令 \(\textit{mid}=\left\lfloor\dfrac{l+r}{2}\right\rfloor\),那我们这里计算所有跨过 \(\textit{mid}\) 的空隙,递归求出 \([l,\textit{mid}]\) 以及 \([\textit{mid}+1,r]\) 中在多边形内的最小 / 大值,这样后者最小值减去前者最大值就是空隙大小了,同时前者最小值和后者最大值就是 \([l,r]\) 中在多边形内的最小 / 大值。

注意两个子区间得有数才能算空隙,不然显然不是内部的空隙。

这样的确可以算出所有空隙,但是复杂度裂了,考虑利用这个多边形的特点 :所有边都是竖直或者水平的。可以证明,对于这样一个 \(m\) 个点的多边形,用大小相同的瓷砖铺满整个平面,那么对于本质不同的瓷砖的多边形经过该瓷砖的方案是 \(O(m)\) 的:

CERC2016G

(图片摘自官方题解)

考虑将所有顶点在的瓷砖标红,其周围四个瓷砖标蓝,那么所有白色瓷砖一定和某一个蓝色瓷砖的方案是相同的。

因此,我们在递归的时候,如果左右两个区域是本质相同的,也就是只有当前考虑的这一位是不同的,那么我们可以只递归一侧,并将其中的空隙数量都 \(\times 2\),这可以通过传入一个参数,算空隙的时候乘以这个参数即可,那么每一次只递归一侧就要将其 \(\times 2\)

考虑如何判断两个区域是本质相同,以当前是竖着切为例:

  • 如果当前区域被水平的多边形边界通过,不影响两边的相同性。
  • 如果当前区域被竖直的多边形边界通过,两边必然不同。
  • 如果当前有顶点严格在当前区域内部,两边必然不同。

横着切同理,我们可以 \(O(m)\) 判断上述内容。

最后,递归的终点,只有一个格子的情况,我们同样可以用射线法 \(O(m)\) 判断其是否在多边形内部,因为所有边都是水平或竖直,可以从中心竖直向上射出一条射线,然后判断和多少条水平的边相交,奇内偶外。

递归过程中如果继续递归两侧说明两边不同,一共有 \(O(n)\) 种分割,由证明易得这种情况最多出现 \(O(nm)\) 次。每出现一次这种情况最多递归 \(O(n)\) 层,每层都需要 \(O(m)\) 判断,因此复杂度为 \(O(n^2m^2)\)

但是题解写复杂度是 \(O(nm^3)\),同时 cf 上也有👴提出是 \(O(n^2m^3)\) 的,不懂,求带。

最后将所有空隙按大小后排序,lower_bound 即可,询问复杂度为 \(O(q \log nm)\)

I

upsolved by Bazoka13 JJLeo

题意

一个由 \(1\)\(9\) 组成的未知串,现在有这个串生成了 \(n\) 个提示,每个提示按如下规则生成:

  1. 随机选一个位置。
  2. 随机往左或往右确定一个方向。
  3. 初始这个提示 \(h\) 是空的序列,从这个位置一直走到尽头,每次遇到一个 \(h\) 中没有的数,就将其加入到 \(h\) 的末尾。

给出这 \(n\) 个提示,问原串最短能是多少,或判断无解。(\(1 \le n \le 10\))

题解

先考虑往右的提示,设提示开始的位置是 \(x_1\le x_2 \le \cdots \le x_m\),那么对于 \(x_i\) 位置开始的提示,一定是进行到某个位置时 (当然也可能是所有数字都经过了后),它可以直接被 \(x_{i+1}\) 位置开始的提示所取代,也就是说后面只要满足 \(x_{i+1}\) 就能满足 \(x_i\),否则 \(x_{i+1}\) 及之后的提示永远都开始不了。

我们考虑处理出 \(t_{i,j,k}\) 表示第 \(i\) 个提示前 \(k\) 个位置都对应上了,现在能否被第 \(j\) 个提示所取代。\(t_{i,j,k}\) 为真当且仅当:

  • \(j\) 个提示的数字全在第 \(i\) 个提示中出现过,因为第 \(i\) 个提示开始位置在第 \(j\) 个位置之前。
  • \(i\) 个提示从 \(k+1\) 个位置开始的数字,要以同样的顺序出现在第 \(j\) 个提示中,否则显然不成立了。

我们再来考虑往左的提示,我们考虑上述过程的逆过程。首先因为 dp 过程是不断向右加数,因此对于每个提示要从后往前填充,当一个提示 \(j\) 走到头时,反过来考虑可以发现此时它是刚开始的,考虑它能否是取代了到了第 \(k\) 个位置的第 \(i\) 个提示,只需看 \(t_{i,j,k}\) 是否为真。如果可以就可以转为第 \(i\) 个提示第 \(k\) 个位置,并继续倒着匹配。

另外还需预处理出 \(L_{i,j}\)\(R_{i,j}\) 分别表示当前向左 / 右的是第 \(i\) 个提示,能否放第 \(j\) 个数,这些都可以根据定义很容易求出。

最后进行 dp,设 \(f_{S,l,i,r,j}\) 表示当前已经完事了的提示集合 \(S\),当前向左的提示 \(l\),从后向前匹配到了位置 \(i\),当前向右的提示 \(r\),从前向后匹配到了位置 \(j\)。设第 \(i\) 个提示的长度为 \(\operatorname{len}(i)\),有以下三个转移:

  • 如果 \(i=1\) 说明 \(l\) 走到头了,可以枚举下一个向左的提示及位置,利用 \(t\) 数组即可;也可以让其作为最后一个靠左的提示,之后都不能选择向左的提示了,可以将 \(l\) 设置为一个特值 \(V\)
  • 如果 \(j=\operatorname{len}(r)\),说明 \(r\) 走到头了,可以枚举下一个向右的提示,利用 \(t\) 数组即可。
  • 新增一个数,根据 \(L\)\(R\) 数组判断是否合法,如果和向右的提示下一位相同,则必须匹配;如果和向左的提示下一位相同,则可匹配可不匹配。

最终的合法状态为选择完了所有的提示,且 \(l=V\)。此外,如果有向右的提示则要求 \(j=\operatorname{len}(r)\)\(S\) 加上 \(j\) 是全集;如果没有向右的提示则要求 \(S\) 就是全集。

因为可以没有向右的提示,初始状态的 \(r\) 也可以用一个特值 \(V\) 来代替,其转移时不要用 \(t\) 数组,直接特判。

使用记忆化搜索,复杂度真是 \(O(\)能过\()\),上界根本不可信,因为光是状态数乘上转移的复杂度就已经裂了,可见有效状态很少。

J

upsolved by JJLeo 2sozx

题意

给定一个长度为 \(n\)\(01\) 串,有以下四种操作:

  • 删掉一个 \(0\),花费 \(o_0\)
  • 删掉一个 \(1\),花费 \(o_1\)
  • 删掉一个 \(0\)\(1\),要求 \(0\)\(1\) 前头,不要求两者挨着,花费 \(r_0\)
  • 删掉一个 \(0\)\(1\),要求 \(0\)\(1\) 后头,不要求两者挨着,花费 \(r_1\)

求把所有数删掉的最小代价。(\(1 \le n \le 10^5\))

题解

现用 \(o_0+o_1\) 去最小化 \(r_0\)\(r_1\)\(r_0\)\(r_1\) 哪个小就贪心把能选的都选了,再选另一个,最后只剩一种数了就单个选即可。

L

solved by Bazoka13

题意

给定三组 \(n\) 个布尔变量的取值,保证互不完全相同,构造一个 2-SAT,使得这三组解恰为全部的解,或判断无解。

题解

如果有一个变量全是一个值,那么直接让 \(x \to \neg x\)\(\neg x \to x\)

剩下 \(6\) 种可能的情况有两两一对,可以让其中等于另一个的反,即 \(x \to \neg y \land y \to \neg x\)

剩下就三种情况了,如果就剩一个了,说明有两组解一模一样,不可能。

如果就剩两个,即两个变量有四种情况其中一种不行,这可以通过一个 \(\to\) 把那种封掉。

如果剩三个,由样例可得 寄了,八种情况封掉五个是不可行的,可以打表证明。

记录

0h:MJX网炸了,调了10min的网,导致开始没看到A的大签到,CSK开C大签到,ZYF冲A大模拟,直接一血(校内),F过的多看F,很sb,ZYF开冲。CSK推完式子冲C,寄了,MJX和ZYF讨论K,发现也是个签到,直接开冲。

1h:ZYF过了,MJX帮着找C的问题,挑了俩bug改完过了。CSK找了个E的递推方式,ZYF直接冲java。MJX看H,很眼熟,想了想直接喂ZYF了

2h:ZYF过了,一起去看B,CSK看L,喂给MJX,MJX没听明白。喂给ZYF,ZYF好像也没明白,CSK自己去优化算法了。

3h:CSK把L乱冲过了,MJX想了个J的大概应该是正解的做法,喂给了ZYF,ZYF直接开冲。

4h:J出bug了,MJX看B,看了看样例解释,发现题nm读错了,sb题直接读成了不可做题,CSK给了个复杂度巨优的算法,MJX直接开冲。然后没开ll,还有奇怪的return,4:58几乎卡时过的。

总结

Dirt

B(+2):没开long long ,MJX多扔了个0,不应该直接return

C(+3):CSK少考虑了几种情况

回到页面顶部