比赛记录(11~20)

11 2024.5.19 测试

1 得分

题目 T1 T2 T3 T4 总分
得分 \(0\) \(30\) \(100\) \(10\) \(140\)

排名:rank \(5\)

2 题解

T1

其实 T1 是本场考试最难的题,因此放到后面讲。

T2

70 pts:

瞄准部分分,我们发现 \(n\le 15\),于是自然想到状压。考虑记录下当前选了的数字,于是定义状态为 \(dp(i,j,S)\) 为枚举到第 \(i\) 位,当前位上放 \(a_j\),同时总共放了的学生集合为 \(S\) 的状态数。

于是可以自然得到转移方程:

\[dp(i,j,S)=\sum dp(i-1,k,S') \]

在合法的条件下直接转移即可,这一部分并不难想到。

100pts:

考虑到题目中有模 \(m\) 的限制,因此我们可以套路的想到将每个数模 \(m\) 处理。

在模完 \(m\) 之后,我们发现,只有余数相同的数才不能放在一起,其他可以随意放置。同时,如果合法,那么将余数相同的数调换仍然合法。于是我们此时只需要考虑余数即可,余数相同的数我们计算阶乘即可。

考虑爆搜,我们现在只需要考虑 \(m\) 个余数。但是此时我们的复杂度仍然高达 \(O(n^m)\),并无太大优化。我们此时希望剪枝,而剪枝中较为有效的方法就是记忆化,这时候我们用一种比较骚的处理方式:对于当前剩下的余数,我们将每一种余数的剩余数量看成一个序列,对这个序列进行哈希,以此进行记忆化。

现在我们提交,发现可以得到 \(80\) pts 的好成绩。那么剩下的问题出在哪里呢?

考虑我们的记忆化。实质上,我们关注的不是原序列的数,甚至也不应该是余数,而是每一种余数出现的次数。例如在 \(m=10\) 时,余数序列 \(3\ 4\ 4\)\(3\ 5\ 5\) 并没有任何本质上的差别。因此,我们实际上处理的序列是,对于 \(i=1,2,\cdots,n\),有多少种余数出现次数为 \(i\)。对这个序列进行哈希就是真正的记忆化。

T3

全场最简单的题。

这道题本质上只要你能做出关键的 \(10\) 分的数据,应该就能做出整道题。那我们先看这关键的 \(10\) 分,就是 \(l=1\) 这个性质。

经过手玩以及推理,我们发现再这样一条性质:对于 \(l=1\) 的任意一个序列,\(1\) 在哪个位置,它的下标就是 \(t(x)\)。原因很简单:如果不选 \(1\),那么整个序列无法结束;一旦选了 \(1\),后面的所有数都会被选。

于是我们可以来看整道题,仿照上面的思路,我们可以求出整个序列中某些关键的数。如果不选这些关键的数,整个序列无法结束;而一旦全部选完,后面的所有数都会被选。显然这些数只需要满足在序列中没有因数即可(我们可以叫它们是这个序列的 “质数”,因此求法就是用简单的埃筛即可),设这些数总共有 \(cnt\) 个。

那么我们只需要关注这些关键数中的最后一个在什么位置。显然可以枚举这个位置 \(i\),那么在 \(i\) 之前必须要放下剩余全部 \(cnt-1\) 个关键数,那么方案书就有 \(A_{i-1}^{cnt-1}\) 种;剩余的 \(n-cnt\) 个数可以随意排列,方案数有 \((n-cnt)!\) 种;最后当前这个位置放哪一个关键数也不确定,因此还有 \(cnt\) 种。最后再乘上 \(i\) 的贡献,于是答案就是:

\[\sum\limits_{i=cnt}^n A_{i-1}^{cnt-1}\times (n-cnt)!\times cnt\times i \]

直接计算即可。

T4

本场最难的题。

首先我们在题目中可以发现这样一个神奇的性质:\(\sum\limits_{i=1}^n\sum\limits_{j=1}^np_{i,j}=n^2\),这就意味着 \(p_{i,j}\) 一定等于 \(1\),也就是每次魔法必定生效。那此时让我们再审视一下这道题,不难发现,这道题与 T1 一模一样,毫无差别。

现在我们开始正式做这个题。首先这道题我们最后变成哪种颜色不确定,因此需要枚举是哪种颜色。又由于求的是期望步数,因此对于每一种颜色我们都要求出是他的概率以及他转移的期望步数。那我们一个一个看。

我们发现这道题与颜色本身并没有太大关系,我们只需要考虑颜色数量即可。设 \(p_i\) 表示一种颜色有 \(i\) 个时,最后序列全部变成该种颜色的概率。那么我们得到,总共选的数量有 \(n(n-1)\) 种,而造成 \(i\) 变化的有 \(2i(n-i)\) 种,其中 \(i(n-i)\) 种是该种颜色变成其他颜色,\(i(n-i)\) 种是其他颜色变成该种该种颜色;当然剩下的情况就是无法转移。于是我们可以得到方程:

\[p_i=\frac{i(n-i)}{n(n-1)}p_{i-1}+\frac{i(n-i)}{n(n-1)}p_{i+1}+(1-\frac{2i(n-i)}{n(n-1)}p_i) \]

现在我们对这个式子进行化简可得:

\[2p_i=p_{i-1}+p_{i+1}\\ p_i-p_{i-1}=p_{i+1}-p_i \]

于是显然 \(p_i\) 构成了一个等差数列。根据定义我们有 \(p_0=0,p_n=1\),于是可以得到 \(p_i\) 的通项公式为 \(\dfrac in\)

接下来我们来看期望步数。设 \(dp_i\) 表示该种颜色有 \(i\) 个时,最后序列全部变成这种颜色的期望步数。注意这个期望步数实在序列变成这种颜色的前提下发生的,也就是我们要关注的实质上是 \(p_idp_i\)。考虑到 \(dp_i\) 的处理并不方便,我们可以直接列出 \(p_idp_i\) 的式子:

\[p_idp_i=\frac 12p_{i-1}dp_{i-1}+\frac 12p_{i+1}dp_{i+1}+p_i\times\frac{n(n-1)}{2i(n-i)} \]

我们解释一下这个式子。首先我们知道从当前颜色改变的概率是 \(\dfrac{2i(n-i)}{n(n-1)}\),那么转移的期望步数自然是它的倒数,同时还需要满足序列是由这种颜色变成的,于是还要乘上概率 \(p_i\)。接下来是前面的期望步数,以 \(i-1\) 为例,首先 \(i\)\(i-1\)\(i+1\) 转移的概率相同,因此要乘 \(\dfrac 12\)。接下来我们要求期望,但是依然都得先满足序列是由这种颜色变成的,于是还要乘上对应概率 \(p_{i-1}\)

那么现在我们换元,令 \(f_i=p_idp_i\),由上式可以得到:

\[f_i=\frac 12 (f_{i-1}+f_{i+1})+\frac{n(n-1)}{2i(n-i)}p_i\\ 2f_i=f_{i-1}+f_{i+1}+\frac{2n(n-1)}{2i(n-i)}\times \frac in\\ f_{i+1}-f_i=f_i-f_{i-1}-\frac{n-1}{n-i} \]

我们得到了一个与 \(p_i\) 很像的递推公式,那么考虑求出通项。由于 \(p_0=0,dp_n=0\),于是 \(f_0=f_n=0\)。现在如果要求出通项或者递推,还差一项,要么求出 \(f_1\),要么求出 \(f_{n-1}\)

现在继续换元,设 \(g_i=\dfrac{n-1}{n-i},d_i=f_{i+1}-f_i\)。那么由上式可得 \(d_{i}=d_{i-1}-g_i\)。同时我们又可以显然发现 \(f_{i+1}=d_i+f_i\)。那么这两个式子就都是显然的数列递推公式,我们可以得到:

\[\begin{aligned} f_{i+1}&=d_i+f_i\\ &=d_i+d_{i-1}+f_{i-1}\\ &=\cdots\\ &=d_i+d_{i-1}+\cdots+d_0+f_0\\ \\ d_i&=d_{i-1}-g_i\\ &=d_{i-1}-g_{i-1}-g_i\\ &=\cdots\\ &=d_0-g_0-g_1-\cdots-g_i \end{aligned} \]

现在我们把下面的 \(d_i\) 再带回上面的式子中,可以得到:

\[\begin{aligned} f_{i+1}&=d_i+d_{i-1}+\cdots+d_0+f_0\\ &=(d_0-g_0-g_1-\cdots-g_i)+(d_0-g_0-g_1-\cdots-g_{i-1})+\cdots+d_0-g_0+d_0+f_0\\ &=(i+1)d_0-ig_0-(i-1)g_1\cdots+g_i+f_0 \end{aligned} \]

那么由于 \(f_0=0\),于是 \(d_0=f_1\)。将两者和 \(g_i\) 都带回上式得:

\[\begin{aligned} f_{i+1}&=(i+1)d_0-ig_0-(i-1)g_1\cdots+g_i+f_0\\ &=(i+1)f_1-ig_0-(i-1)g_1\cdots+g_i\\ &=(i+1)f_1-i\frac{n-1}{n-1}-(i-1)\frac{n-1}{n-2}+\cdots+\frac{n-1}{n-i} \end{aligned} \]

现在将 \(i+1\) 换成 \(i\) 可得:

\[\begin{aligned} f_{i}&=if_1-(i-1)\frac{n-1}{n-1}-(i-2)\frac{n-1}{n-2}+\cdots+\frac{n-1}{n-i+1}\\ &=if_1+(n-1)(\frac{i-1}{n-1}+\frac{i-2}{n-2}+\cdots+\frac{i-i+1}{n-i+1}) \end{aligned} \]

发现此时后面括号内式子形式很好,\(i\)\(n\) 同步,那我们就可以直接令 \(i=n\),得:

\[\begin{aligned} f_{n}&=nf_1+(n-1)(\frac{n-1}{n-1}+\frac{n-2}{n-2}+\cdots+\frac{n-n+1}{n-n+1})\\ &=nf_1+(n-1)(n-1) \end{aligned} \]

由于 \(f_n=0\),便可以求出:

\[nf_1+(n-1)^2=0\\ f_1=\frac{(n-1)^2}{n} \]

现在我们终于可以直接递推整个 \(f\) 数列了!最后直接累加答案即可。

12 2024.6.2 测试

1 得分

题目 T1 T2 T3 T4 总分
得分 \(0\) \(70\) \(10\) \(49\) \(129\)

排名:rank \(6\)

2 题解

T1

最简单的题目。观察到 \(n\) 并不是很大,并且题目只要求出现长度为 \(3\) 的等差数列,所以我们可以考虑枚举第一个数字以及公差。维护一个桶,储存每个数字出现的位置,通过首项和公差计算然后通过桶来判断即可。

这样做复杂度为 \(O(Tn^2)\),常数较小可以卡过去。

T2

首先这道题分为两部分,也就是每个男生被一个女生选到的概率,还有就是出现逆序对的期望个数。

先看第一部分。

考虑对于第 \(i\) 个女性,假设它的列表中有 \(s_i\) 个男性。现在看第 \(j\) 个男性被选到的概率,如果在第一轮就被选上,那么概率是 \((1-p)^{j-1}p\);如果第二轮才被选到概率为 \((1-p)^{s_i+j-1}p\);第三轮被选到概率为 \((1-p)^{2s_i+j-1}p\)……

不难发现,每一轮选中第 \(j\) 个男生的概率构成了一个公比为 \((1-p)^{s_i}\) 的等比数列。于是我们利用等比数列求和可以得到对于第 \(i\) 个女性,选到第 \(j\) 个男性的概率是:

\[P(i,j)=\frac{(1-p)^{j-1}p}{1-(1-p)^{s_i}} \]

接下来看第二部分。

首先明确一点,由于逆序对的贡献始终为 \(1\),因此期望就等于概率。所以我们只需要求出出现逆序对的概率即可。

我们考虑第 \(i\) 个女性的第 \(j\) 个男生,编号为 \(p_{i,j}\),只要在 \(i\) 之前的女性有比 \(p_{i,j}\) 编号大的男生,就有可能出现逆序对。将出现这些男生的概率求和,再乘上 \(P(i,j)\) 就是当前出现一个逆序对的概率。所以我们可以得到如下式子:

\[E(i,j)=P'(i,j)=\sum_{k=1}^{i-1}(\sum_{p_{k,l}>p_{i,j}} P(k,l))\times P(i,j) \]

此时暴力求这个式子的时间复杂度是 \(O(nm^2)\) 的,显然无法通过。

容易发现,如果我们将女生编号看作 \(x_i\),男生编号看作 \(y_i\)。现在对于一个点,只需要求出所有 \(x_j<x_i\)\(y_j>y_i\) 的点的概率之和,然后乘上这个点的概率即可。不难发现这就是一个二维偏序,用树状数组直接简单维护即可。时间复杂度降为 \(O(m\log n)\),可以通过。

T3

首先容易想到,对于这样的题目,通常考虑区间 dp。那么这道题同样如此。

考虑分析题目条件,不难发现,所有合法的超级括号序列的两边应该都是括号。同时我们可以将所有超级括号序列分成两部分:

  • 定义的 \(1,3\) 条可以归为一类,这一类序列两边的括号是互相匹配的。
  • 定义的第 \(2\) 条可以归为一类,这一类序列两边的括号是和中间的括号匹配的。

显然两类的计算方法不同,所以要分开求解。设 \(f(i,j)\) 表示区间 \([i,j]\) 为第一类合法序列的方案数,\(g(i,j)\) 表示区间 \([i,j]\) 为第二类合法序列的方案数。

首先来看第一类的求解。还是需要进一步分类讨论。

注意下面讨论的基础都是 \(s_i\)\(s_j\) 能够成为匹配的括号。

  1. ()

显然,如果满足 \(i\)\(i+1\) 能够成为匹配的括号(注意类似 (? 也算),则 \(f(i,i+1)=1\)

  1. (S)

为了满足这里以及后面判断 S 型字符串的需要,定义 \(p(i,j)\) 表示区间 \([i,j]\) 是否可以全部都是 * 且长度是否不超过 \(k\) 的字符串。显然 \(p(i,j)=1\) 时就代表 \([i,j]\) 是一个 S 型串。

现在这一型字符串对应的转移方程就很简单了:

\[f(i,j)+=p(i+1,j-1) \]

至于如何求 \(p(i,j)\),暴力 \(O(n^2)\) 枚举即可。

  1. (A)

这一部分也很简单,直接给出方程:

\[f(i,j)+=f(i+1,j-1)+g(i+1,j-1) \]

  1. (SA)(AS)

我们直接枚举断点,然后判断即可。两者的方程分别为:

\[f(i,j)+=\sum_{k=i+1}^{j-2}(f(k+1,j-1)+g(k+1,j-1))\times p(i+1,k)\\ f(i,j)+=\sum_{k=i+1}^{j-2}(f(i+1,k)+g(i+1,k))\times p(k+1,j-1) \]

显然这些方程的转移复杂度都是 \(O(n^2)\)\(O(n^3)\),可以接受。

下面看第二类的求解。

其实第二类的转移方程只有一个,因为我们可以将 AB 型看成是 S 串长度为 \(0\)ASB 型。枚举两个断点,转移方程如下:

\[g(i,j)+=\sum_{k=i}^{j-1}\sum_{l=k+1}^j(f(i,k)+g(i,k))\times f(l,j)\times p(k+1,l-1) \]

但是这一类的求解难度并不在转移方程上。我们发现,这个方程的转移复杂度是 \(O(n^4)\),需要优化。我们会发现后面一部分 \(f(l,j)\times p(k+1,l-1)\) 只有三个参数,于是自然想到预处理。定义一个 \(sg(i,j)\),式子如下:

\[sg(i,j)=\sum_{k=i+1}^jf(l,j)\times p(i+1,k-1) \]

我们在 dp 过程中一边求 \(f,g\),一边求出 \(sg\) 数组,然后利用它优化上面的转移方程,最后方程为:

\[g(i,j)+=\sum_{k=i}^{j-1}(f(i,k)+g(i,k))\times sg(k,j) \]

发现此时两个数组的求解都是 \(O(n^3)\) 的了。

所以整道题的转移复杂度现在都在 \(O(n^3)\) 以下,复杂度 \(O(n^3)\),可以通过。

T4

首先我们会想到这样一个显然的 dp:设 \(dp(i,0/1)\) 表示在第 \(i\) 层上,从左 / 右端点落下后,走到原点的最短路径。

那么我们以 \(dp(i,0)\) 举例。假如从第 \(i\) 层的左端点落下,掉到第 \(j\) 层上,那么转移方程就是:

\[dp(i,0)=\min\{dp(j,0)+|l_i-l_j|,dp(j,1)+|l_i,r_j|\} \]

容易发现,如果我们构造一个线段构成倒金字塔的数据,那么这个方程就会被卡到 \(O(n^2)\),无法通过。

考虑瓶颈其实是在求出从第 \(i\) 层掉下落在那一层上。考虑到我们每一个线段都会覆盖掉之前出现的线段,因此如果我们将 \(x\) 轴单独拿出来,就可以认为这是一个线段覆盖的问题,而我们要求的其实就是一个下标对应的线段编号。

整理上面的操作可以看出,我们实际上只需要维护区间覆盖、单点查询。显然使用线段树优化即可。

时间复杂度为 \(O(n\log (B_i-A_i))\)

3 挂分

  1. T1 复杂度没有卡过去,\(100\to 0\)
  2. T2 树状数组做法写炸,\(100\to 70\)

13 2024.6.9 测试

1 得分

题目 T1 T2 T3 T4 总分
得分 \(100\) \(0\) \(10\) \(0\) \(110\)

排名:rank \(8\)

2 题解

T1

考虑 dp。我们发现 \(m\) 过大,所以考虑对 \(n\) 进行 dp。

\(dp_i\) 表示走到第 \(i\) 个矿点能拿到的矿的最大和,现在我们就要考虑上一个矿点从何转移而来。

考虑到每一次跳的距离都是由 \(4\)\(7\) 组合而成的,如果注意力惊人的话会发现如下数字:

  • \(18=1\times4+2\times 7\)
  • \(19=3\times4+1\times 7\)
  • \(20=5\times4+0\times 7\)
  • \(21=0\times4+3\times 7\)
  • \(22=18+4\)
  • \(23=19+4\)
  • \(\cdots\)

于是可以得到,所有距离大于等于 \(18\) 的都可以直接跳过去。而剩下的的可以跳过的距离特判即可(有 \(4,7,8,11,12,14,15,16\))。

现在我们从 \(i\) 往前枚举,如果 \(b_i-b_j< 18\),那么判断 \(b_i-b_j\) 是否是上面那些特殊的距离,如果是则有转移 \(f_i=\max\{f_j+a_i\}\)

当我们找到第一个满足 \(b_i-b_j\ge 18\)\(j\) 的时候,意味着 \(1\sim j\) 的所有矿点都可以直接跳到 \(i\),于是 \(dp_i\) 就应该取它们的最大值加 \(a_i\)

考虑到直接求最大值是 \(O(n)\) 的。由于这是一个较为简单的前缀最大值,因此记录一个 \(max_i\) 数组即可。

T2

观察到平均数可能为小数,但是题目中并没有关于小数的信息。考虑拆开 \(V\) 的式子:

\[\begin{aligned} &(n+m-1)\times \sum(A_i-Avg)^2\\ =&(n+m-1)\times \sum({A_i}^2-2A_iAvg+Avg^2)\\ =&\sum((n+m-1){A_i}^2-2A_iAvg(n+m-1)+(n+m-1)Avg^2)\\ =&(n+m-1)\sum{A_i}^2-2\times\sum A_i\times Avg\times (n+m-1)+\sum(n+m-1)Avg^2\\ =&(n+m-1)\sum{A_i}^2-2\times\sum A_i\times \sum A_i+(n+m-1)^2Avg^2\\ =&(n+m-1)\sum{A_i}^2-2\times(\sum A_i)^2+(\sum A_i)^2\\ =&(n+m-1)\sum{A_i}^2-(\sum A_i)^2 \end{aligned} \]

现在我们希望使用 dp 求解,但是此时的式子还不能支持我们完成 dp。考虑进一步计算贡献,假如当前已走的路径的方格的平方和\(P\)和的平方\(Q\),则当前的 \(V=(n+m-1)P-Q^2\)

如果此时加入 \(a_{i,j}\) 这个数字,则 \(V\) 会变成 \((n+m-1)(P+{a_{i,j}}^2)-(Q+a_{i,j})^2\)。此时计算两个 \(V\) 的差即为加入 \(a_{i,j}\) 的贡献,为:

\[(n+m-2){a_{i,j}}^2-2Qa_{i,j} \]

发现此时只有 \(Q\) 未知,所以我们在 dp 中要维护这个 \(Q\)。于是自然想到设 \(dp(i,j,S)\) 表示走到点 \((i,j)\),之前的和为 \(S\) 时,\(V\) 的最小值。转移方程即为:

\[dp(i,j,S+a_{i,j})=\min\{dp(i-1,j,S)+(n+m-2){a_{i,j}}^2-2Sa_{i,j},dp(i ,j-1,S)+(n+m-2){a_{i,j}}^2-2Sa_{i,j}\} \]

最后答案即为 \(\min\{dp(n,m,S)\}\)

T3

我们注意到当 \(m=0\) 的时候就是一个非常朴素的换根 dp,那现在考虑 \(m\) 不为 \(0\) 的情况。

首先发现 \(m\le 15\),也就意味着题目中的位运算只对后 \(4\) 位二进制产生影响,也就是小于 \(16\) 的部分。

仍然考虑换根 dp。设 \(f_i\) 表示根节点为 \(i\) 的子树内所有点到 \(i\) 的距离之和,\(p(i,j)\) 表示根节点为 \(i\) 的子树内所有点到 \(i\) 的距离中,小于 \(16\)(即模 \(16\))的部分的值为 \(j\) 的点的个数。此时我们会有如下转移方程(设 \(v\)\(u\) 的儿子,\(w\) 为边权,\(siz\) 为子树大小):

\[f_u=\sum f_v+w(u,v)\times siz_v\\ p(u,(i+w(u,v))\bmod16)=\sum p(v,i) \]

现在我们考虑换根,也就是子树外的部分。设 \(g_i\) 表示以 \(i\) 为根节点时,所有点到 \(i\) 距离之和;\(q(i,j)\) 表示以 \(i\) 为根节点时,所有点到 \(i\) 的距离中,小于 \(16\)(即模 \(16\))的部分的值为 \(j\) 的点的个数。此时我们会有如下转移方程:

\[g_v=g_u-f_v-w(u,v)\times siz_v+w(u,v)\times(n-siz_v)+f_v\\ q(v,(i+2w(u,v))\bmod16)=q(u,(i+w(u,v))\bmod 16)-p(v,i)+p(v,(i+2w(u,v))\bmod16) \]

现在我们考虑求出最后答案。首先对于一个点 \(i\),应该将 \(g_i\) 中所有距离小于 \(16\) 的部分先刨去,因为它们需要异或 \(m\)。刨去后进行异或然后再加回去,这样对于点 \(i\) 的答案就是:

\[g_i-q(i,j)\times j+q(i,j)\times (j\ \operatorname{xor}\ M) \]

但是此时我们会将点 \(i\) 到自己的距离 \(0\) 异或上 \(M\),导致答案多出了 \(M\),减去即可。

T4

首先仍然考虑树形 dp。题目中要求将所有人送回去走的最短路径,那么其实可以分为两类:最终停留在子树内或最终停留在子树外。因此我们应该设出 \(4\) 个 dp 数组 \(f(i,1/2/3/4)\),分别表示根节点为 \(i\) 时,走完子树回到 \(i\) 的最短路 / 走完子树停留在子树内的最短路 / 走完子树外回到 \(i\) 的最短路 / 走完子树外停留在子树外的最短路。显然考虑 up and down 求解。

先看子树内的部分。如果子树内没有特殊点就不用再扫,直接给 \(0\) 值即可。否则有如下转移方程(设 \(v\)\(u\) 的儿子,\(w\) 为边权):

\[f(u,1)=\sum f(v,1)+2w\\ f(u,2)=f(u,1)-\max\{f(v,1)-f(v,2)+w\} \]

在第二个转移方程中,我们可以这样理解:停留在子树内的最短路,其实就是走完回到 \(i\) 的最短路再减去最后一段回到 \(i\) 的距离的最大值。而这个最大值自然就是 \(f(v,1)-f(v,2)+w\)

接下来考虑子树外。同理可以得到如下转移方程(\(p\)\(u\) 除了 \(v\) 另外的一个儿子,之间边权为 \(w'\)):

\[f(v,3)=f(u,3)+(f(u,1)-2w-f(v,1))+2w\\ f(v,4)=f(v,3)-\max(w+w'+f(p,1)-f(p,2),w+f(u,3)-f(u,4)) \]

理论和上面的子树内一致,都是找出走回 \(i\) 那一段最大的路径然后减去。

算出 \(f\) 数组之后我们就可以直接得到答案了,为 \(\min\{f(i,1)+f(i,4),f(i,2)+f(i,3) \}\)

3 挂分

  • T2 多组数据没有换行,\(100\to 0\)
  • T3 骗分没有减去最后的 \(M\)\(50\to 10\)

14 CSP-J 模拟赛1

1 得分

题目 T1 T2 T3 T4 总分
得分 \(100\) \(60\) \(0\) \(52\) \(165\)

排名:rank \(4\)

2 题解

T1

正解并不难想。首先看到最少属性的修改器,想到二分答案。然后我们在 check() 中贪心,将数组排序后从头开始枚举,区间最长到多少就取到多少,然后看区间总数与 \(k\) 的关系即可。

能够划分为一个区间的标准就是对于区间 \([l,r]\),满足 \(a_r-a_l\le 2\times mid\) 即可。

T2

5 pts

首先不难发现对于这种情况,如果前 \(m\) 个确定了,那么后面的也就确定了(第 \(m+1\) 个必须是第 \(1\) 个、第 \(m+2\) 个必须是第 \(2\) 个……以此类推)。所以方案数自然是 \(k!\)

another 45 pts

不难想到此时的状态只有 01,想到状压 dp。设 \(dp(i,S)\) 表示以 \(i\) 结尾的后 \(m\) 个数的状态为 \(S\) 的方案数。那么转移方程就是 \(dp(i,S)=\sum dp(i-1,S')\),其中 \(S'\) 是能够转移到 \(S\) 的上一位的后 \(m\) 个数。

上面这些可以拿到 \(50\)​ pts 的高分了。下面来看正解。

100 pts

首先观察这么一个东西:对于任意一个合法的 \(m\) 个数,将每一种酒最后一次出现的位置记作 \(1\),其他全部记作 \(0\)。例如 1121313,将其记作 0010011。不难发现,在这种记法之下,只要满足最后一位为 \(1\)\(1\) 的个数恰为 \(k\) 的状态都是合法状态。

于是我们沿用 \(45\) 分的状压思路,设 \(dp(i,S)\) 表示以 \(i\) 结尾的后 \(m\) 个数的状态为 \(S\) 的方案数。我们计算出上一位能够转移到的状态 \(S'\),转移方程就仍然是 \(dp(i,S)=\sum dp(i-1,S')\)

不过值得注意的是,对于一种状态 \(S\),其对应的摆放方式有很多,考虑如何计算。我们从后向前枚举状态的每一位,假设当前遍历到的 \(1\) 的个数为 \(num\)。若当前位置上是 \(1\),则方案数乘上 \(k-num\);否则方案数乘上 \(num\)。设最后计算出的方案数有 \(p(S)\) 种,则初始化就是 \(dp(m,S)=p(S)\)

最后答案就是 \(\sum dp(n,S)\)

T3

30 pts

我们暴力搜即可,注意到自顶向下的暴力不是很直观而且有些难实现,所以考虑自下而上的合并。我们从 \(n\) 个叶子节点出发,枚举相邻的区间并合并,直到合并为区间 \([1,n]\)。然后我们暴力枚举每一个区间并在线段树上找出区间个数累加取最小值即可。

100 pts:

首先 \(f_{l,r}\) 的下界显然是 \(1\)。那么现在关注什么情况下 \(f_{l,r}\) 的下界会增加。

假设对于当前查询区间 \([l,r]\),在线段树上有一个区间 \([L,R]\),且该区间从 \(k\) 处划分。如果 \([L,R]\)\([l,r]\) 有交集但不包含,且 \([l,r]\) 经过 \(k+0.5\) 的话,显然我们就必须要走 \([L,R]\) 的两个子树,而答案也就随之加一。

既然这样,我们就可以将原先每一个查询区间的答案看作是线段树上每一个区间的贡献,我们对这个进行区间 dp。设 \(dp(l,r)\) 表示线段树上出现区间 \([l,r]\),其子树内对答案产生如上述的贡献的最小值。那么转移方程就是:

\[dp(l,r)=\min_{k=l}^{r-1}\{dp(l,k)+dp(k+1,r)+num(l,r,k)\} \]

后面的 \(num(l,r,k)\) 就表示与 \([l,r]\) 有交集但不包含,且经过 \(k+0.5\) 的查询区间个数。现在问题就在于如何求这个东西。

我们不妨设两个数组,\(n1_i\) 表示经过 \(i+0.5\) 位置的区间个数,\(n2_{l,r}\) 表示包含区间 \([l,r]\) 的区间个数,那么显然 \(num(l,r,k)=n1_i-n2_{l,r}\)\(n1_i\) 是好求的,但是如果暴力求 \(n2_{l,r}\)\(O(n^2q)\) 的,显然复杂度会炸。

我们考虑使用二维前缀和的方法,我们先求出区间为 \([l,r]\) 的区间个数。然后对于要求的区间 \([l,r]\)\(n2_{l,r}\) 就是包含区间 \([l-1,r]\) 的区间个数加上包含区间 \([l,r+1]\) 的区间个数,再减去包含区间 \([l-1,r+1]\) 的区间个数,最后加上区间为 \([l,r]\) 的区间个数。这样我们的复杂度就是 \(O(n^2)\) 的。

最后的总复杂度就是区间 dp 的 \(O(n^3)\) 了。

T4

20 pts

考虑大力 dp,设 \(dp(i,j)\) 表示开到 \(i\) 位置且剩余油量为 \(j\) 的最小花费,我们直接 \(O(n^2C+nC^2)\) dp 即可。

another 20 + 12 pts:

由于数据比较优秀,所以实际上 sub \(1\sim 5\) 也满足特殊性质 \(A\)

考虑怎样做特殊性质 \(A\),显然我们每一次加油都可以走到后面任意的地方。那么考虑贪心,显然我们走到后面第一个比自己油价小的地方然后再走比自己走完要优,所以我们就这么走,然后累加答案即可。

100 pts

仍然考虑上面的贪心做法,我们每一次能走的路程显然最多就是 \(C\),如果再这个范围内有油价比自己小的站点就将油加到能走到那里即可;否则,我们找到能够走到的站点中油价最小的一个,先再自己这个位置将油加满,然后走到那个站点即可。此时会有剩余的油量,不过这不影响答案,然后从新到的点继续贪心即可。

这样做显然是最优的,不过暴力找区间最小值可能会被卡到 \(O(n^2)\),利用 ST 表优化一下即可。

15 CSP-J 模拟赛2

1 得分

题目 T1 T2 T3 T4 总分
得分 \(100\) \(100\) \(30\) \(20\) \(250\)

排名:rank \(7\)

2 题解

T1

通过样例不难发现,假设这个 \(X\) 从高到低每一位为 \(a_i\),则对于答案中从高到低第 \(i\) 位的答案就是 \(\sum\limits_{j=1}^i a_j\)(先不考虑进位)。显然这个式子可以利用前缀和简单维护。

当然此时我们还没有考虑进位。考虑到对于最后的结果,其大小不可能超过 \(2X\),也就是说最多会进一位,特判即可。

T2

首先我们不妨先表示出将第 \(i\) 个位置上的 Y 挪到第 \(j\) 个位置上的 Y 需要多少步(不妨假设 \(i<j\))。设 \(s_i\) 表示第 \(i\) 个位置及第 \(i\) 个位置前有多少个 Y,显然步数为 \((j-i-1)-(s_j-s_i-1)=j-i-s_j+s_i\)。容易发现这个式子的形式比较好,我们就设 \(p(i)=i-s_i\),于是上式就变为 \(p(j)-p(i)\)

由于上面我们假设了 \(i<j\),所以大小关系需要判断。由于 \(p\) 显然存在单调性,所以 \(i,j\) 的大小实际上就是 \(p(i),p(j)\) 的大小。换句话说,对于任意的 \(i,j\),其所需的步数总是 \(|p(i)-p(j)|\)

现在让我们将所有的 Y 单独提出来看,我们将 \(p(i)\) 的定义修改为第 \(i\)Y(注意此时计算公式中的 \(i\) 仍然表示原数组的下标)。容易得到的结论是,将所有的 Y 靠向一个 Y 最后连成一段的步数一定最优,而最后连成一段的 Y 在将 Y 提出来之后也是连续的。

因此,将 Y 提出来之后,我们只需要判断连续的区间需要挪动的步数即可。那么现在对于区间 \([l,r]\),将所有 Y 靠到第 \(i\)Y 的步数就是 \(\sum\limits_{j=l}^r|p(i)-p(j)|\)。我们自然想要让这个式子的值最小,不难想到绝对值的几何意义,也就是将它们全部靠到这个区间的中间最优,也就是 \(mid=\lfloor\frac{l+r}{2}\rfloor\)。然后区间挪动的步数就能 \(O(1)\) 计算了。

最后我们考虑如何枚举区间。显然如果区间长度为 \(x\) 的可行,那么长度为 \(x-1\) 的一定也可行;如果区间长度为 \(x\) 的不可行,那么长度为 \(x+1\)​ 的一定也不可行。显然这满足单调性,于是我们二分区间长度即可。

总时间复杂度为 \(O(n\log n)\)

T3

60 pts

显然可以直接大力搜索,深搜后判断交换次数,或者广搜扩展然后去重,都可以通过。

但是这一部分比较卡常,如果用太多 STL 无法通过。

100 pts

发现我们只关注前面放了多少 KEY,那我们就设 \(dp(i,j,k,l)\) 表示当前已经放置了 \(i\)K\(j\)E\(k\)Y,且交换次数为 \(l\) 的字符串个数。

接下来这一部分略微有点绕。首先可以得到的是,对于同种字符交换与不交换没有区别,所以我们就不交换同种字符。既然这样,我们就可以得到的结论是,如果这个字符原本是第 \(i\) 次出现,那么现在它还是第 \(i\) 次出现。

接下来我们以 K 举例。假如下一位上我们要放 K,我们就要找到第 \(i+1\)K 并把它挪过来。现在考虑它要挪过来的步数。记它在原数组中前面有 \(y\)E,如果 \(j<y\),那么剩下的 \(y-j\)E 会堆在当前的 T 前面,于是就要再换这么多次;否则,一定是后面的 E 主动换到了前面,不会改变当前 K 的相对位置,所以不需要额外挪动。

对于 Y 是同理的,不过值得注意的是,由于 EY 不完全相同,因此两者的数量需要分开讨论。也就是说,如果下一位上我们要放 K,还需要的步数就是 \(\max(y-j,0)+\max(z-k,0)\)。如果这个值为 \(c\),那转移方程就是:

\[dp(i+1,j,k,l+c)\ +\!\!=dp(i,j,k,l) \]

对于剩下的两种情况,同理可得。最后答案就是 \(\sum\limits_{i=1}^Kdp(x,y,z,i)\)

T4

暴力分就不说了。我们发现如果想要 dp,问题就在于这个前 \(K\) 大的条件。此时我们发现,如果人为规定第 \(K\) 大,那么 dp 就比较容易了。而第 \(K\) 大最多也只有 \(n^2\) 个,暴力枚举即可。

\(dp(i,j,k)\) 表示走到点 \((i,j)\),比当前枚举的 \(x\) 大的数总共有 \(k\) 个的最小和。那么接下来需要分三种情况讨论:

  • \(a_{i,j}>x\),那么必须选这个数,方程为 \(dp(i,j,k)=\min\{dp(i-1,j,k-1)+dp(i,j-1,k-1)\}+a_{i,j}\)
  • \(a_{i,j}<x\),那么一定不选这个数,方程为 \(dp(i,j,k)=\min\{dp(i-1,j,k),dp(i,j-1,k)\}\)
  • \(a_{i,j}=x\),那么这个数可以进入前 \(K\) 大也可以不进入,所以要对上面两个转移方程取 \(\min\)

最后我们对所有 \(x\) 对应的 \(dp(n,m,K)\) 取最小值即为答案。

16 CSP-J 模拟赛3

1 得分

题目 T1 T2 T3 T4 T5 总分
得分 \(50\) \(65\) \(45\) \(20\) \(0\) \(180\)

排名:rank \(7\)

2 题解

T1

首先显然是将所有数字按照模 \(3\) 的结果分类,然后贪心分组。显然分组方式只有 \(000,111,222,012\) 三种形式。

但是这道题目有一个问题:单纯的先选 \(012\) 和单纯的先在每个余数中取三个都会有对应的 Hack 数据,也就是说,单纯的贪心并没有正确性,会挂到 \(95/85pts\)

我们考虑这样一件事,如果选取的 \(012\) 个数大于等于 \(3\),那么实际上选 \(3\)\(012\) 和选 \(000,111,222\) 各一个没有区别。因此,我们可以认为,\(012\) 的个数最多为 \(2\)。枚举这个个数然后对结果取最大值即可。输出方案就比较简单了。

T2

30pts

直接暴力展开字符串然后枚举即可。

another 30pts

容易猜到,在 \(n\) 这么大的情况下很有可能会出现循环,那么我们就记录每一个小分数 \(a:b\) 最早出现的位置 \(p(a,b)\),以及此时两者的大分数 \(pA(a,b),pB(a,b)\)。如果在遍历的过程中在相同的位置遇到相同的 \(a:b\),说明出现循环,而一个循环内两者的大比分增量分别为 \(A-pA(a,b),B-pB(a,b)\)。我们直接跳过这些循环,然后特判循环之前和之后的部分即可。

显然这样做的正确性完全取决于数据的循环节的长度。我们发现有 \(30\%\) 的部分分满足小比分一定小于等于 \(11\),因此此时我们 \(a,b\) 的组合方案数最多只有 \(12\times 12=144\) 种,于是至多在 \(144\) 轮后会出现循环,复杂度就是 \(O(144k)\)

当然由于这个算法比较玄学,可能还能多拿 \(5\) pts。

100pts

上面的算法与正解其实只差临门一脚,我们不难发现 \(30\%\) 的部分分规定了小比分一定小于等于 \(11\),而如果其他部分也能满足这个性质,上面的算法就是正解。

考虑到如果比分全部大于 \(11\),实际上就是看谁先比对方的分数大 \(2\)。因此此时我们不再关注分数的绝对大小,而只关注相对大小,于是想到将它们减去 \(\max(a,b)-11\),让小比分降到 \(11\) 及以下,显然这样做不会影响最后比分。

于是我们就通过这样的方式让所有数据都满足了任意时刻小比分小于等于 \(11\),上面的算法就有了正确性。复杂度还是 \(O(144k)\)

T3

30pts

爆搜即可。

another 5pts

考虑枚举唯一的 | 放在哪,利用前缀与 和 后缀与计算即可。

100pts

首先我们证明一个引理:将所有 & 放到 | 前面,一定能取到最优结果。

证明:考虑连续三个数 \(a,b,c\)。如果我们的式子是 a | b & c,根据位运算性质可以知道,这个式子最大值是 \(c\);而如果式子是 a & b | c,则这个式子最小值是 \(c\)

因此将 & 放到 | 前面一定不会更劣,那么不断调整,最后在整个序列上将 & 放到 | 前就一定能得到最优解。

于是我们就可以得到答案,得到答案之后我们就考虑贪心求解方案。对于当前位置,如果放下 |,在后面按照最优方式放置运算符依然可以得到最大结果,这一位上就放 |;否则就放 &

T4

30pts

理论上爆搜 \(O(2^n)\) 应该能过,但是常数过大的话会被卡到 \(20\sim25\) pts 不等。

正确做法应该是利用状压记录方案,然后进行记搜。

100pts

看到 \(n\le 500\),显然想到区间 dp。考虑设 \(f(l,r)\) 表示能否将区间 \([l,r]\) 的人全部消尽。显然单凭 \([l,r]\) 本身是不可能消尽的,于是我们就需要以 \(l-1,r+1\) 为基础来进行。转移方程就比较简单了:

\[f(l,r)=f(l, k-1)\and f(k+1,r)\and(\gcd(a_k,a_{l-1})>1\or\gcd(a_k,a_{r+1})>1) \]

注意这里如果我们每次求 \(\gcd\) 会在 \(O(n^3)\) 的基础上在加上一个 \(\log a_i\),这样可能会 T。我们提前用 \(O(n^2\log a_i)\) 的复杂度预处理出 \(\gcd\) 即可。

现在我们再设 \(dp(i)\) 表示在前 \(i\) 个人中,不消除第 \(i\) 个人能消除的最多的人,转移方程就是:

\[dp(i)=\max\{dp(j)+[f(j+1,i-1)]\times(i-j-1)\} \]

当然为了判断最后一个能不能消除,我们可以 dp 到 \(n+1\) 的位置,最后答案就是 \(dp(n+1)\).

T5

60pts

首先我们需要先推出一个贯穿全文的式子:当前面听过了 \(k\) 首歌,且保证满足听完第 \(k+1\) 首新歌时恰好听完的情况下,听完这 \(k+1\)​ 首歌的概率为:

\[\begin{aligned} P(k+1)&=\frac kn\times(1+\frac 1n+(\frac1n)^2+\cdots)\times\cdots\times\frac 1n\times(1+\frac kn+(\frac kn)^2+\cdots)\times \frac 1n\\ &=\frac kn\times\frac{n}{n-1}\times\cdots\times\frac 1n\times \frac{n}{n-k}\times \frac1n\\ &=\frac{k!(n-k-1)!}{n!} \end{aligned} \]

于是我们就考虑利用状压枚举这 \(k+1\) 首歌,如果满足上面提到的前面听过了 \(k\) 首歌,且听完第 \(k+1\) 首新歌时恰好听完的要求,就计算出对应的答案并累加即可。

85pts:

考虑到我们并不关注每一首歌的具体编号,只关注他们的和的范围。我们枚举作为最后一首歌的编号 \(x\),则此时前面的歌的快乐度总和只能在 \([S-a_x,S)\) 之间。于是想到利用背包,设 \(dp(i,j)\) 表示在选了 \(i\) 首歌且总快乐度为 \(j\) 的方案数,因为每一次我们 dp 不能包含 \(x\),所以对于每一个 \(x\) 我们都要 dp 一遍,复杂度就是 \(O(n^3S)\) 的。

我们枚举 \(j\),然后根据 \(i\) 套用上面的 \(P\) 的公式计算并累加即可。

100pts

考虑到上面 dp 不优在我们每一个 \(x\) 都要进行一次 dp,所以考虑只在外面进行一次 dp。我们考虑原先在 dp 的过程中 \(x\) 这个位置都产生了那些贡献,将这些贡献减去即可,这样的复杂度就是 \(O(nS)\) 的,总复杂度就是 \(O(n^2S)\) 了。

17 CSP-J 模拟赛4

1 得分

题目 T1 T2 T3 T4 总分
得分 \(100\) \(0\) \(25\) \(10\) \(135\)

排名:rank \(7\)

2 题解

T1

首先我们发现,每一次只能从右向左给东西,于是我们对于 \(i\) 这个位置,只考虑 \(i+1\) 位置即可。我们接下来分类讨论一下:

  • 如果 \(i+1\) 位置能将 \(i\) 补齐,直接补齐即可。
  • 否则,我们可以看作将 \(i+1\) 位置上的东西补给 \(i\),此时 \(i+1\) 位置上就会出现需求量大于储存量的问题,接下来我们对 \(i+1\) 进行同样操作即可。因为从 \(x\to y\to z\) 传递和直接 \(x\to z\) 传递没有区别,所以设置多少个中转站不会影响答案,这样做就能得到正确答案。

T2

这个 T2 和上一场的 T4 有着异曲同工之妙。我们考虑设 \(dp(i)\) 表示在 \(i\) 位置喊做核酸,且满足让所有 \(l<i\) 的人听见所需要的最少的喊的次数。

现在考虑向后转移,如果 \(i\) 可以转移到 \(j\),则说明在区间 \([i+1,j-1]\) 区间内不需要喊人,也就是说没有任何一个人的区间满足 \(i<l\le r<j\),此时我们就会有方程 \(dp(j)=\min\{dp(i)+1\}\)

现在考虑怎么判断上面的转移条件,我们设 \(R_i\) 表示以 \(i\) 为左端点的区间中右端点的最小值,那么上述条件等价于 \(\min\limits_{k=i+1}^{j-1}R_k\ge j\),容易发现对于固定的 \(i\),我们在枚举 \(j\) 的时候就可以顺便求出这个最小值,所以复杂度就是单纯的 \(O(1024^2)\)

和之前的 T4 一样,我们直接 dp 到 \(1024+1\) 的位置即可记录下全部答案。现在考虑求方案数,其实这一部分就很简单了,设 \(f(i)\) 表示得到 \(dp(i)\) 这个最小值的方案数,显然只需要在转移的时候累加即可,同样 dp 到 \(1024+1\) 就能求出最后答案。

T3

首先我们先利用背包求出每一颗龙珠能够取到的数字有哪些,显然这一部分是 \(O(\sum x_im)\) 的,最大达到了 \(7\times 10^9\),显然会爆炸。我们考虑这里的 dp 只需要存储 \(0/1\),所以可以使用 bitset 优化 \(\frac1 {64}\) 的常数。

现在我们先计算出每一颗龙珠单独的能量值(也就是乘上对应的系数)然后排序,我们令七元组 \((a,b,c,d,e,f,g)\) 表示第一颗龙珠取第 \(a\) 大能量值,第二颗取第 \(b\) 大能量值……这个方案。显然能量和最大的方案就是 \((1,1,1,1,1,1,1)\),但是第二大的方案可能是 \((2,1,1,1,1,1,1),(1,2,1,1,1,1,1)\cdots\)。此时不难想到利用优先队列,每次取出最大的一个,然后扩展出七个方案再放回队列,这样我们取出 \(k\) 次就能得到第 \(k\) 大的方案。当然要注意不能放入重复的方案。

这样我们最多取出 \(k\) 次,也就是最多放回 \(7k\) 个元素,复杂度就是 \(O(7k\log 7k)\) 的,总复杂度就应该是 \(O(7k\log 7k+\frac{\sum x_im}{64})\),可以通过。

T4

首先手玩几组数据可以发现,每一次龙取得位置是没有固定的方案的,因此单纯的进行区间 dp 似乎不可行。

但是我们也会发现这样一个问题,假如龙当前吃掉了 \(x\) 位置上的龙珠且该龙珠不在区间的两端,它对小明的答案是暂时不会造成影响的;而如果等到 \(x\) 成为区间端点的时候,此时再吃与之前吃效果是一样的。

于是我们将龙的决策就可以改写成:

  • 每一次可以吃掉两端的龙珠,也可以不吃。每不吃一次可以积攒一次吃的机会,在后面每一次吃的时候都可以消耗一个机会多吃一次。

这样龙和小明的决策都是在两端的了,就可以进行区间 dp。设 \(f(l,r,k)\) 表示到小明的回合,决策区间为 \([l,r]\),且当前龙有 \(k\) 次吃的机会的情况下,小明能拿到的龙珠价值的最大值;\(g(l,r,k)\) 表示到龙的回合,决策区间为 \([l,r]\),且当前龙有 \(k\) 次吃的机会的情况下,小明能拿到的龙珠价值的最小值。转移方程就是:

\[f(l,r,k)=\max\{g(l+1,r,k+1)+a_l,g(l,r-1,k+1)+a_r \}\\ g(l,r,k)=\max\{f(l,r,k),f(l+1,r,k-1),f(l,r-1,k-1) \} \]

直接 \(O(n^3)\) 区间 dp 即可。

18 CSP-J 模拟赛5

1 得分

题目 T1 T2 T3 T4 T5 总分
得分 \(100\) \(100\) \(70\) \(35\) \(100\) \(405\)

排名:rank \(2\)

2 题解

T1

显然算式最终可以化成 \(Ax+B\) 的形式,然后暴力枚举 \(x\) 求最大值即可。复杂度 \(O(|S|+n)\)

T2

记录当前剩余的未匹配的左括号个数,如果遍历到右括号但未匹配的左括号个数为 \(0\),显然这个右括号必须改为左括号,答案加一。我们设遍历完整个字符串后未匹配上的左括号有 \(x\) 个,我们只需要将其中 \(\dfrac x2\) 个左括号改成右括号即可。复杂度 \(O(|S|)\)

T3

70pts

不难发现这是一个多重背包问题,物品的个数是 \(0\sim m\),价值是 \(1\sim n\),直接 \(O(n^4)\) 暴力 dp 即可。由于常数较小,可以通过 \(n\le 200\) 的数据。

100pts

考虑原题相当于对集合进行如下操作:

  • 向集合中加入一个元素 \(0\)
  • 给集合所有元素加上 \(1\)

我们设 \(dp_{i,j}\) 表示当前集合有 \(i\) 个数,总和为 \(j\) 的方案数,那么根据上面第二种情况对应的就是 \(dp_{i,j-i}\),但是考虑第一种情况的时候我们需要考虑 \(m\) 的限制。显然一次加入的 \(0\) 的个数不能超过 \(m\) 个,于是想到从 \(\sum\limits_{k=1}^mdp_{i-k,j}\) 转移。

但是我们无法确定前面的 \(dp\) 状态有没有放 \(0\),所以考虑再设一个 \(g_{i,j}\) 表示当前集合有 \(i\) 个数,总和为 \(j\),且没有 \(0\) 的方案数,那么第一种情况对应的方案数就是 \(\sum\limits_{k=1}^mg_{i-k,j}\),于是转移方程就是

\[dp_{i,j}=dp_{i,j-i}+\sum\limits_{k=1}^mg_{i-k,j} \]

同时还有:

\[g_{i,j}=f_{i,j-i} \]

但是此时第一个方程的转移还是 \(O(n^3)\) 的,不难发现后面的和式是连续求和的,于是可以使用前缀和优化 dp,复杂度优化至 \(O(n^2)\)

T4

本题正解是搜索,但 std 不能保证在确定的复杂度之内通过数据范围内的所有数据,故暂且认为是错题。

T5

20pts

考虑到 \(n\le 20\) 可以状压,我们就状压枚举分割点,然后暴力计算代价取最小值即可。

复杂度 \(O(n2^n)\)

60pts

看到题目中要求的最大值最小,不难想到二分答案。二分答案后我们相当于规定了每一段和的最大值,然后求出划分点和的最小值,与二分的答案比较即可得出能否可行。

显然想到利用 dp 求解,设 \(dp_i\) 表示在 \(i\) 处分割后,分割前 \(i\) 项所需的最小分割点代价之和,则转移方程为:

\[dp_i=\min_{sum_{i-1}-sum_j\le mid}\{dp_j+a_i\} \]

直接暴力的话复杂度是 \(O(n^2)\) 的,可以通过 \(60\) pts。

100pts

不难发现转移区间是一段连续区间,单调队列优化 dp 即可,总复杂度为 \(O(n\log \sum a_i)\)

19 CSP-S 模拟赛1

1 得分

题目 T1 T2 T3 T4 总分
得分 \(80\) \(35\) \(90\) \(25\) \(230\)

排名:rank \(1\)

2 题解

T1

考虑到 \(n\le 300\),不难想到利用 Floyd 进行求解。这时就考察我们对于 Floyd 的理解了,我们知道 Floyd 的状态应该是 \(f(k,x,y)\),表示经过点 \(1\sim k\) 的从 \(x\)\(y\) 的最短路径。容易发现这里面并没有限制 \(k\) 的顺序,因此结合这道题我们可以想到,将点权从小到大排序后枚举中转点 \(k\),这样最大值就只能是 \(a_x,a_y,a_k\) 了,然后利用这个进行转移即可。

预处理复杂度 \(O(n^3)\),回答是 \(O(1)\) 的。

T2

二分做法是不具有决策单调性的,但是由于本题求解的是可行解,因此可以通过较多数据点。

通过数据点 \(8\sim9,10\),想到需要对单个格子进行分类讨论:

  • \(k\le a_{i,j}\le 2 k\),直接输出即可。
  • \(a_{i,j}>2k\),这个格子绝对不能选。

那么现在我们矩形中剩下的能选的格子全部是 \(<k\) 的,现在假如我们取出了一个和 \(S\ge k\) 的子矩阵,继续分类讨论:

  • \(S\le 2k\),直接输出即可。

  • 否则,考虑这样一种方式:我们一行一行去切这个矩形,如果当前行的和 \(S'\ge k\),则继续分类讨论:

    • \(S'\le 2k\),直接输出即可。
    • 否则,一个格子一个格子去删这一行,直到满足在 \([k,2k]\) 之间。

    否则如果当前行和 \(S'<k\),将这一行之间删去,然后判断剩下的矩形,重复上述过程即可。

注意到由于上述两种删除操作中(矩阵删行,行删格子),原先的部分都满足 \(>2k\),删除的部分都 \(<k\),这样删完一定会满足 \(S\in[k,2k]\),因此当找到和 \(S\ge k\) 的子矩阵时,就一定找到了一个解。

那么现在考虑怎么求,显然这个矩阵越大越好,那么我们就去找极大子矩阵,利用单调栈或者悬线法求解即可。

T3

发现 \(a_i,x\le 300\),同时还要求欧拉函数,不难想到利用欧拉函数公式直接求解。我们写出公式的原形式:

\[\varphi(n)=n\times \prod\limits_{i=1}^k(1-\frac{1}{p_i}) \]

其中 \(p_i\)\(n\) 的质因子。利用筛法可以发现 \(300\) 以内只有 \(62\) 个质数,于是不难想到在线段树上直接维护出区间内包含的质因子,然后区间查询出区间的积以及质因子,利用欧拉函数的公式计算答案即可。

这里考虑怎样维护质因子,可以利用 long long 状压或者 bitset,两者复杂度一致,只在常数上有略微区别。至于线段树只是一颗朴素的区间修改区间查询线段树,懒标记维护即可。

T4

这一题的思考瓶颈就在于根号分治。如果会根号分治的话从子任务推向正解还是容易的。

Subtask 1~3

直接在两个点之间暴力跳即可,具体来讲,利用倍增求出当前点的 \(c\) 级祖先,直到深度小于两点的 LCA,将答案累加起来即可。

由于树可能是一条链,所以复杂度是 \(O(n^2)\) 的。

Subtask 4~5

这一部分相当于是奖励,对正解帮助不大。考虑到因为点权为 \(1\),那么跳过的权值和就是跳的次数 \(+1\),而跳的次数可以有两点间距离求出,复杂度就是 \(O(n\log n)\) 的。

Subtask 6~11

这一部分就可以提示出正解了。我们考虑当树化为一条链时,相当于要求出在区间 \([x,y]\),且与 \(x,y\)\(c\) 同余的所有下标对应的数的和。如果学过的话一眼就能看出这是根号分治的模板题。我们设定阈值 \(B=\sqrt n\),若 \(c\le B\),预处理出与当前点模 \(c\) 同余的点的前缀和,利用差分 \(O(1)\) 求解即可;若 \(c> B\),那么跳的次数绝对不超过 \(\sqrt n\) 次,暴力跳即可。

Subtask 12~20

沿用根号分治的思路,我们设 \(sum_{i,j}\) 表示从点 \(i\) 以步长为 \(j\) 跳到根节点的权值总和,那么当 \(c\le B\) 时,利用当前点与 LCA 的差分就可以 \(O(1)\) 求出答案;而当 \(c> B\) 时,利用 Subtask 1~3 的方式暴力跳即可,最多跳 \(\sqrt n\) 次即可求出答案。

注意到实现时需要大量求解 \(k\) 级祖先,使用传统倍增复杂度是 \(O(n\log n+n\sqrt n\log n)\) 的,有点难看但完全可以通过。利用长链剖分可以 \(O(1)\) 求出 \(k\) 级祖先,复杂度可以降为 \(O(n\log n+n\sqrt n)\)

20 CSP-S 模拟赛2

1 得分

题目 T1 T2 T3 T4 总分
得分 \(57\) \(52\) \(10\) \(40\) \(159\)

排名:rank \(11\)

2 题解

T1

考虑利用贪心,在峰值买入比特币,谷值卖出比特币,这样一定能取到最优。

T2

首先我们将 \(1\) 的情况先排除掉,如果 \(Ax<y\),则说明选一个 \(A\) 不如选 \(A\)\(1\) 优,我们就将选一个 \(A\) 的代价改为 \(Ax\)\(B\) 同理。

现在考虑放置 \(A,B\)。不妨假设选 \(A\) 的性价比比选 \(B\) 更高,那么我们考虑 \(A\) 的个数,显然最多是 \(\dfrac nA\) 个,但是显然暴力枚举会炸;考虑到既然选 \(A\) 的性价比比选 \(B\) 高,那么如果 \(B\) 选择的数量超过 \(A\) 个,将这 \(A\)\(B\) 换成 \(B\)\(A\) 显然更优,于是 \(B\) 的个数一定是小于 \(A\) 个的。

这时候我们发现,两者的个数上限分别是 \(\dfrac nA\)\(A\),显然这两个中必然有一个小于 \(\sqrt n\),我们只需要枚举小于的那一个即可,复杂度 \(O(T\sqrt n)\)

T3

牛波一结论题。

首先得出这样一个结论:出现的质因子集合相同的两个数可以互换,且所有 \(\lfloor\frac ni\rfloor\) 相同的质数 \(i\) 也可以互换,同时同构的排列只能通过这两种方式得出。

接下来给出证明:

首先考虑质因子集合相同的两个数,显然两个数若原来就满足条件,那么显然交换后仍然满足对应的互质条件。

现在考虑 \(\lfloor\frac ni\rfloor\) 相同的质数,对于一个质数 \(i\),它可以与 \(1,2,3,\cdots,\lfloor\frac ni\rfloor\) 相乘得到一些数,那么对应的另一个数 \(j\),可以与 \(1,2,3,\cdots\lfloor\frac nj\rfloor\) 相乘得到一些数;若要交换 \(i,j\),则对应的 \(2i,2j\)\(3i,3j\)……也要一起交换,那么自然就要满足 \(\lfloor\frac ni\rfloor=\lfloor\frac nj\rfloor\),因此 \(\lfloor\frac ni\rfloor\) 相等的质数也可以互换。

至于怎么看出这个结论的,注意力即可。

T4

20pts

暴力枚举每一个黑点求出 LCA 然后取最大值即可。

another 20pts

既然满足父亲标号在 \([1,i-1]\) 内随机,那么树高显然就是期望 \(\log n\) 的。我们考虑查询时从每一个点开始暴跳父亲,假设当前点所在子树根节点为 \(g\),父亲为 \(f\),那么若除了 \(g\) 的子树以外的 \(f\) 的子树有黑色节点,则 \(f\) 就可以作为当前的答案,跳到根节点取最大值即可。复杂度 \(O(n\log n)\)

100pts

考虑到上述思路是直接查询自己的答案,我们不妨转换思路,考虑每一个点对其余点答案的贡献。

如果新添加的黑色点的为 \(x\),那么显然 \(x\) 子树内的所有点的答案都可以是 \(x\);接着我们开始暴跳父亲,当前点所在子树根节点为 \(g\),父亲为 \(f\),那么除了 \(g\) 的子树以外的 \(f\) 的子树的节点的答案都可以是 \(f\)​。

显然这里我们需要给子树赋值并求出最大值,利用 DFS 序建立线段树,维护区间修改单点查询即可。

现在我们不难发现,这个算法的时间复杂度与上面并没有本质区别。但是此时我们仔细思考一下,如果我们跳到了节点 \(x\),之前 \(x\) 的子树中就已经存在黑色节点了,那么显然这个节点 \(x\) 的其他部分已经被另外的黑色节点更新过了,同时它的父亲也被更新过了,此时我们就不需要再向上跳了,直接推出即可。

这样做的复杂度就是 \(O(n+m)\) 的,可以通过。

posted @ 2024-06-07 17:18  UKE_Automation  阅读(69)  评论(0)    收藏  举报