做题记录

P5369 [PKUSC2018] 最大前缀和。
很好的观察性质题。
首先,我们考虑一个集合为 \(S\) 的前缀的最后一个点能不能成为整个序列的做大前缀和所在位置。显然,我们必须要求 \(S\) 自身的最大序列是 \(sum_S\),同时要求对于 \(T = \complement_U S\),满足 \(T\) 的每一个前缀必须 \(< 0\)。注意到这个性质之后我们设计状态。我们设 \(f_S\) 表示前者,\(g_S\) 表示后者。对于前者,我们枚举每一个 \(i \in S\) 作为最后一个元素,只要把 \(i\) 刨除去之后前面的剩下是 \(\ge 0\) 的即可。对于 \(g\) 我们可以考虑刷表法转移即可。最后答案是 \(\sum f_S \times g_{\complement_U S} \times sum_S\)。
思维难度:蓝;代码实现:黄;实际:紫。

P3643 [APIO2016] 划艇。
考虑朴素 DP。我们设 \(f_{i, j}\) 表示前 \(i\) 个学校,第 \(j\) 个学校派出了 \(j\) 个队伍的方案数。但是我们发现 \(j\) 太大不方便转移,考虑进行离散化。我们把区间 \([a_i, b_i + 1]\) 离散化到一个数轴上,每次考虑相邻的两个点。
假设现在考虑的是第 \(j\) 和 \(j + 1\) 之间构成的区间。我们从 \(i\) 向前枚举到 \(k\),表示从 \([k, i - 1]\) 这些学校我们都在这个区间范围内。所以,我们的问题变成了从 \([0, len]\) 的区间中选择 \(w\) 个数字,要求所有非零数字严格单调递增。方案数显然是 \(\binom{len + w - 1}{w}\),因为我们必须钦定第 \(i\) 个选择。
然后我们列出 \(f_{i, j} = \sum_{1 \le k \le i - 1} \sum_{1 \le p \le j - 1} \binom{len + pos - 1}{pos} \times f_{k, p}\)。我们发现后面这个式子可以直接前缀和优化,前面的可以滚动数组优化即可。复杂度 \(O(n^3)\)。
思维难度:蓝;代码实现:蓝;实际:紫。

CF1781F Bracket Insertion。
这题太神了,不愧是 tourist。
我们考虑什么情况下括号串合法。很明显,我们把 \((\) 视为 \(+1\),把 \()\) 视为 \(-1\),对于这样剩下的一个整数序列,我们满足最后一位前缀和是 \(0\),并且之前的每一步前缀和都必须 \(\ge 0\)。
因此,我们设 \(f_{n, x}\) 为还剩下 \(n\) 次操作,我们要在前缀和为 \(x\) 的后面进行一次操作,能够达到合法状态的方案数。这里的合法状态指的就是每一步的前缀和都满足 \(\ge 0\)。
我们考虑如果加入的是 \(()\) 括号串,那么我们前缀和数组就会从 \(x\) 这一位变成了 \(x, x + 1, x\)。如果我们插入的是 \()(\) 也是同理的。所以,我们假设在 \(n - 1\) 次操作时,我们就把 \(j\) 次分给了 \(x + 1\) 或 \(x - 1\),\(i\) 次分给了第一个 \(x\),那么剩下的 \(n - 1 - i - j\) 分配给了第二个 \(x\)。
状态转移方程:\(f_{n, x} = \sum_{0 \le j \le n - 1} \sum_{0 \le i \le n - j - 1} p \times \binom{n - 1}{j} \times \binom{n - j - 1}{i} \times f_{i, x} \times f_{j, x + 1} \times f_{n - 1 - j - i, x} + (1 - p) \times \binom{n - 1}{j} \times \binom{n - j - 1}{i} \times f_{i, x} \times f_{j, x - 1} \times f_{n - 1 - j - i, x}\)
但是这样转移其实是 \(O(n^4)\) 的。我们考虑如何进行优化。
我们通过惊人的注意力发现,其实我们的中间项是一致的!所以我们把两边的都提出来,令 \(g_{n, x} = \sum_{0 \le i \le n} \binom{n}{i} \times f_{n, x} \times f_{n - i, x}\)。
于是乎,我们的原来式子就变成了:
\(f_{n, x} = \sum_{1 \le j \le n - 1} \binom{n - 1}{j} \times [p \times f_{j, x + 1} + (1 - p) \times f_{j, x - 1}] \times g_{n - j - 1, x}\)。
代码很简短,思路超级诡异。
思维难度:黑;代码实现:绿;实际:紫。

AT_arc108_d [ARC108D] AB。
首先现在的字母只剩下 AB,所以我们第一步必须插入的是 \(c_{AB}\)。
考虑进行分类讨论。
首先如果 \(c_{AB} = A\),我们此时得到的序列是 \(AAB\)。
接下来如果我们一直在 \(AB\) 之间插入的一定是 \(A\),这是一种情况,最后是 \(AA...B\);
如果我们考虑 \(c_{AA} = A\),那么答案肯定和上面的一致。如果 \(c_{AA} = B\),那我们还得接着分类讨论,此时我们得到的序列就是 \(ABAB\),会出现 \(BA\) 的贡献。
如果 \(c_{BA} = A\),我们充分发扬人类智慧,会发现这个东西最后生成的序列会是若干个 \(A\),一个 \(B\),若干个 \(A\),一个 \(B\),并且以 \(B\) 结尾。我们发现此时第一种的 \(AA...B\) 也满足这种格式。我们设 \(f_{i, 0/1}\) 表示考虑前 \(i\) 位,第 \(i\) 位填入的是 \(A\) 或者 \(B\)。列出状态转移方程:\(f_{i, 0} = f_{i - 1, 0} + f_{i - 1, 1}\),\(f_{i, 0} = f_{i - 1, 0}\)。
接下来考虑 \(c_{BA} = B\)。我们手玩几组样例之后会发现答案貌似是 \(2^{n - 3}\)!
证明:第一,我们知道这个序列一定是以 \(AB\) 结尾,并且以 \(A\) 开头。考虑现在的状态是 \(A + S + AB\)。如果第二位是 \(A\),根据现在我们的情况,下一次操作的第二位可以变成 \(B\),也可以不变。以此类推,我们可以证明对于中间的 \(n - 3\) 位其实我们随便取就行。
\(C_{AB} = B\) 的情况对称。
思维难度:青;代码实现:红;实际:青。

P3214 [HNOI2011] 卡农。
我们考虑把无序化问题转化为有序化问题。我们不妨设 \(f_i\) 表示总共有 \(i\) 个集合的合法方案数。此时我们可以发现一个很好的性质,就是如果我们已经确定了 \(i - 1\) 个集合的话,我们直接推出这个集合的元素。因为前 \(i - 1\) 中出现次数为偶数的一定不会再次出现,前 \(i - 1\) 出现为奇数的这里一定不会出现。这就直接满足了第三个性质。
考虑容斥,因为我们无法满足前两个条件。首先考虑空集,如果成为空集说明 \(i - 1\) 必定合法,所以这里剪掉的情况就是 \(i - 1\);接下来我们考虑冲突。我们如果冲突的话,直接减掉两个集合的数字一定也是合法的,所以首先有一个 \(f_{i - 2}\) 的情况。接下来,我们考虑从 \(i - 1\) 个数字里面找出一个和 \(i\) 冲突,所以还剩下 \(i - 1\) 中可能性。最后,我们再考虑有多少种集合可以冲突。因为我们钦定了前 \(i - 2\) 种方法,我们这里直接选择 \((2^n - 1 - (i - 2))\) 即可。最后我们列出状态转移方程:
\(f_i = A_{2^n - 1}^{i - 1} - f_{i - 1} - f_{i - 2} \times (i - 1) \times (2^n - i + 1)\)
最后因为求的是无序方案数,再除以 \(m!\) 即可。
思维难度:蓝;代码实现:蓝;实际:紫。

P2490 [SDOI2011] 黑白棋。
超级超级好的一道题。
首先我们可以把题意转化成一个博弈论问题:我们现在有一个石子序列:\(a_1, a_2, ..., a_{\frac{k}{2}}\),每次先手或者后手可以从中选不超过 \(d\) 个石子堆,从中拿走任意正数个元素。最后拿走石子的人为胜者,在什么情况下先手存在必胜策略。
这就是著名的 \(k - \text{NIM}\) 博弈。我们抽象成一个一般化的问题:现在的石子数量分别是 \(a_1, a_2, ..., a_n\),每次从中选择不超过 \(k\) 个石子堆。先给出答案:当且仅当对于任意 \(j\),所有 \(a_i\) 的第 \(j\) 位是 \(1\) 的个数是 \(k + 1\) 的倍数时,先手必败。
证明:我们把上述状态成为 \(P\),也就是必败状态;我们把不是必败状态的称之为 \(N\),也就是必胜状态。
接下来先证明必败如何一次转化为必胜。此时我们手中有一个必败状态,不论我们从哪一位置选择 \(r\) 个,都不能使取走的这一位 \(s_i\) 再一次变化为 \(0\)。所以定存在 \(P - N\) 的策略。
接下来考虑是否存在 \(N - P\) 的合法策略。
考虑使用数学归纳法。我们从高位向低考虑。假设我们现在已经操作了 \(m\) 个石子堆,现在处于第 \(i\) 个位置(也就是对于任意 \(j > i\) 都有 \(s_j = 0\)),并且这 \(m\) 里面现在第 \(i\) 位置上有 \(a\) 个二进制是 \(1\),\(b\) 个二进制是 \(0\)。显然 \(a + b = m\)。
分三种情况考虑。

  • 如果 \(a \ge s_i\),那么我们操作很简单,接着从这 \(a\) 个里面选择 \(a - s_i\) 个减掉这么多石子即可;
  • 如果 \(b \ge (k + 1) - s_i\),现在我们在这 \(b\) 个中选择 \(s_i\) “加上” \(2^i\) 个个石子即可;注意到我们之前已经在至少 \(j > i\) 位置上拿走了 \(2^j\) 个石子,所以这一步实际上也让石子数量减少;
  • 最后,如果上述两个条件都不满足,则必有 \(a < s_i\),\(b < (k + 1) - s_i\),我们选择另外找来 \(s_i - a\) 个石子堆,从这里拿走 \(2^i\) 个石子。此时的操作数量是 \(m + s_i - a = m - a + s_i = b + s_i < k + 1\),所以此时至多取走 \(k\) 堆石子。

综上所述,以此类推,必定会有一步合法方案使 \(N - P\) 和 \(P - N\)。并且,对于所有的 \(a_i = 0\),这明显使必败态,且满足 \(P\)。所以命题得证!
接下来我们考虑如何统计方案数。考虑容斥。一共有 \(n\) 个位置,我们选择 \(k\) 个的总方案数是 \(\binom{n}{k}\)。考虑如何统计不合法的方案数。我们设 \(f_{i, j}\) 表示高于 \(i\) 的二进制位,还剩下了 \(j\) 个石子没有使用的必败方案数。很明显我们的目标就是把第 \(i\) 位置上面的 \(s_i = 0\)。
列出状态转移方程:\(f_{i, j - l \times (d + 1) \times 2^i} = f_{i + 1, j} \times \binom{\frac{k}{2}}{l \times (d + 1)}\)
解释一下,我们现在已经有 \(i + 1\) 前面的所有位置满足要求,这一位置我们要找出 \(k + 1\) 的倍数个,所以我们枚举了 \(l\)。同时,因为我们一共有 \(\frac{k}{2}\) 堆石子,我们还需要从这些堆石子当中选出 \(l \times (d + 1)\) 堆石子。
最后我们统计答案:\(\sum_{1 \le i \le n - k} f_{0, i} \times \binom{\frac{k}{2} + i}{i}\)。这是因为我们还剩下 \(i\) 个棋子,我们这 \(i\) 个棋子肯定分布在 \(\frac{k}{2}\) 这些成对的之间,共有 \(\frac{k}{2} + i\) 个从中选 \(i\)。
最后我们容斥一下即可。复杂度 \(O(nk \log n)\)。
思维难度:蓝;证明难度:紫;代码难度:青;实际难度:紫。

P15726 [JAG 2023 Summer Camp #3] Best parentheses。
说实话感觉 CCF 近几年越来越爱出这种反悔贪心了。
这个题难度很小。我们考虑每次找出左括号的时候把它放进一个优先队列;如果遇到一个右括号,考虑如果它和堆顶元素之和 \(> 0\) 的话我们就选择。
很明显这是错误的,原因是我们可能和后面的一个发生冲突。我们注意到 \(a_i + a_k = a_i + a_j - a_j + a_k\),所以我们每次统计完 \(a_i + a_j\) 的时候都把 \(-a_j\) 也放进队里面这样就可以反悔了。
思维难度:黄;代码实现:橙;实际:青。

CF1485F Copy or Prefix Sum。
挺不错的一道题。
我们设 \(f_{i, j}\) 为前 \(i\) 个元素,前缀和为 \(j\) 的方案数。很明显,我们考虑第 \(i\) 位的选择:

  • 如果选择 \(a_i = b_i\),那么一定有 \(f_{i, j} = f_{i - 1, j - b_i}\)
  • 如果选择前缀和,那么一定有 \(f_{i, b_i} = \sum f_{i - 1, x}\)

我们观察可得,第一种操作类似于全局偏移,而第二种操作类似于全局加。所以我们直接维护一个 \(sum\) 即可。
思维难度:青;代码实现:青;实际:青。

P2127 序列排序。
小清新思维题。
我们考虑对于 \(i\) 向最终的位置 \(s_i\) 连边。注意到这个的出度和入度都是 \(1\),所以一定构成了一个环。既然是一个环,我们有两种选择:

  • 我们选择环上的最小值,然后依次交换;
  • 或者,我们也可以选择把全局最小值和最小值进行交换,然后依次和剩下的元素进行交换,最后再把这两个交换回去即可。

正确性显然,复杂度 \(O(n)\),瓶颈居然在于找环。
思维难度:青;代码实现:黄;实际:青。

P1053 [NOIP 2005 提高组] 篝火晚会。
没想到卡了我半天的居然是构造合法序列。
首先我们要构造出合法序列。我们令 \(a_1 = 1\),则 \(a_2 = r_1\),\(a_n = l_1\)。接下来我们每次 check 一下 \(r_{a_{i - 1}} = a_{i - 2}\) 或者 \(l_{a_{i - 1}} = a_{i - 2}\)。这样构造显然合法。
然后我们考虑对于每一个点走到自己的目标节点。有两种选择:顺时针或者逆时针。顺时针我们定义为走到 \(n\) 然后往回;逆时针我们定义为走到 \(1\) 然后往回。
很明显,第一种我们走动次数是 \(i - a_i\),第二种则是 \(i + a_i\)。分别统计答案,取 max,然后我们钦定这些点不动,每次操作剩下的,很明显也就是 \(n - maxn\) 即可。
思维难度:青;代码实现:绿;实际:青。

P6268 [SHOI2002] 舞会。
典典题。
很明显我们给出的是一个二分图,所求的答案是二分图最大独立集。注意,对于一般图来说,二分图最大独立集是 NP 问题,但是对于二分图来说不是。我们考虑匈牙利算法,即对二分图计算最大匹配。答案就是 \(n - 二分图最大匹配\)。
证明也非常容易。二分图最大匹配中的点我们都只选择 \(1\) 个,那么很明显这个就符合答案。
所以我们直接染色,然后进行二分图最大匹配即可。
思维难度:绿;代码实现:绿;实际:青。

P3702 [SDOI2017] 序列计数。
小小计数题。
当我们看到“要求这 \(n\) 个数中必须含有质数”的时候我们就发现这个肯定不好做,考虑容斥。
我们设 \(f_{i, j}\) 表示前 \(i\) 个数,所有数的和加在一起是 \(j\)(当然是在模 \(p\) 意义下)的方案数。状态转移方程:\(f_{i, j} = \sum_{0 \le k \le p - 1} f_{i - 1, k} \times cnt_{j - k}\)。我们发现这个形式非常优美,可以使用矩阵进行转移!
同理,我们考虑设 \(g_{i, j}\) 表示前 \(i\) 个数,所有数加在一起是 \(j\) 的方案数,但是只用合数。状态转移方程和上面的同理。所以我们考虑对于 \(f\) 和 \(g\) 分别进行矩阵优化即可,最后答案很明显就是 \(f_{n, 0} - g_{n, 0}\)。
思维难度:青;代码实现:蓝;实际:蓝。

P12543 [APIO2025] 转杆。
我们先从最简单的情况入手:
如果 \(n = 2\),那么一定是两条边垂直的时候达到最优;
如果 \(n = 3\),其实吧我们画画图发现很多种情况都会令答案达到最优,但是直觉告诉我们直角一定更优;
如果 \(n = 4\),我们画图分析,很明显当且仅当两天直线垂直的时候达到最优,可以根据 \(n = 3\) 的时候数学归纳法即可。
我们首先对于这些线段进行排序,直接猜结论就是 \((i, i + \frac{n}{2})\) 这些进行配对。
考虑数学归纳法进行证明。当 \(n = 2k\) 的时候成立,但是 \(n = 2k + 1\) 在我们的条件下一定成立;当 \(n = 2k + 1\) 的时候,我们考虑新加入的 \(2k + 2\) 这条线段和前面的线段所形成的夹角 \(\Delta\) 以及我们可能“损失”的一些夹角。我们注意到这些线段的夹角一定优于前面的,这很显然。所以我们直接贪心就是对的。
思维难度:蓝;代码实现:橙;实际:青。

P14254 分割(divide)。
很好的观察性质题。
首先我们注意到,所有的 \(d_{b_i}\) 一定全部相等,否则不满足题设要求啊。接下来既然可以这样,那我们不妨统计出对于一个深度 \(d\) 的所有点的子树最大深度。然后我们考虑对于一个深度如何计算答案。
我们先来枚举一下第一个位置,不妨假设此时最大深度是 \(m\),所以 \(S_1 = [d, m]\)。接下来因为 \(S_1\) 一定是其他集合的子集,所以剩下集合一定会在这个 \(m\) 的后面,同时必定会有至少一个也选择的的是 \(m\)。
我们记录 \(cnt1\) 为以 \(d_i = m\) 的个数,\(cnt2\) 为 \(d_i > m\) 的个数。首先我们考虑对于 \(S_j\)(\(2 \le j \le k\))中存在一个 \(d_j = m\),那么方案数可以容斥一下:\(A_{cnt1 + cnt2 - 1}^{k - 1} - A_{cnt2}^{k - 1}\)。
接下来我们考虑如何计算不存在 \(d_i = m\)。很明显我们必须存在 \(cnt2 = k - 1\)。然后贡献自然就是 \(A_{k - 1}^{k - 1} = (k - 1)!\)。最后统计输出即可。复杂度 \(O(n \log n)\)。
思维难度:蓝;代码实现:蓝;实际:蓝。

P11226 [COTS 2019] 排名 Vezuv。
很一般的一道题。
先建立字典树,然后我们钦定 \(s_i\) 为最小的话那么我们遍历字典树上的每一个节点然后和其他节点连一条有向边,最后拓扑排序即可。注意判定是否存在 \(s_j\) 为 \(s_i\) 的前缀。
思维难度:黄;代码实现:黄;实际:青。

P3228 [HNOI2013] 数列。
很神的一道题!
首先,我们设原序列是 \(a_1, a_2, ..., a_k\),那么满足的条件一定是 \(1 \le a_{i + 1} - a_i \le m\),并且 \(a_k \le n\)。我们考虑令 \(d_i = a_{i + 1} - a_i\),那么一定对于所有的 \(1 \le i \le k - 1\) 会有 \(1 \le d_i \le m\),同时 \(a_1 + \sum d_i = a_k \le n\)。所以我们考虑枚举差分数列,假设差分数组的和为 \(S\),那么答案贡献就是 \(n - S\)。
考虑列出式子:
\(\sum_{1 \le i \le m^{k - 1}} n - \sum_{1 \le j \le k - 1} d_{j}\)
我们把 \(n\) 提出来,然后我们现在要求的式子就是:
\(n \times m^{k - 1} - \sum_{1 \le i \le m^{k - 1}} \sum_{1 \le j \le k - 1} d_{i, j}\)
考虑如何计算后面的这一大堆式子。因为我们知道每一个数字出现的都是 \(1\) 到 \(m\),所以我们只需要知道每一个数字出现的次数即可。我们发现,这些数字一定是从 \([1, m]\) 等概率选取的,我们又知道总共的次数是 \(\frac{m^{k - 1} \times (k - 1)}{2}\),然后我们再根据小学数学所学的乘在一起即可。所以最后的式子很简洁:
\(n \times m^{k - 1} - \frac{m^{k - 1} \times (k - 1) \times (m + 1)}{2}\)
思维难度:紫;代码实现:橙;实际:紫。

P2573 [SCOI2012] 滑雪。
这个题还是比较基础的。首先我们通过 DFS 遍历一下所有能够到达的节点并且保留边。这里需要注意一下,我们保留的边必须是所有的,不能和我似的手欠删了一大部分边;
然后我们考虑在有向图上建立最小生成树。很明显,我们要比较两个值:首先是终点的高度,必须是高的在前;如果终点高度一致,比较 \(len\),小的在前即可。这样的话就做完了。
思维难度:绿;代码实现:绿;实际:青。

P11830 [省选联考 2025] 幸运数字。
说实话感觉 luogu 评级给的有点低。
我们考虑假设我们已知了一个 \(x\) 要如何求出答案。
我们假设现在小于 \(x\) 的一共有 \(a\) 个,等于 \(x\) 的恰好有 \(b\) 个,大于 \(x\) 的恰好有 \(c\) 个。我们可以列出以下的不等式:
\(a < b + c\) 同时 \(a + b \ge c\)。
如果 \(l_{i, 2} \le x \le r_{i, 2}\),也就是我们的区间恰好包含了 \(x\),我们贪心选择肯定都是 \(x\),因为 \(b\) 增加肯定更优。假设我们此时固定 \(a\),那么 \(c\) 的选择区间就是 \([a - b + 1, a + b]\)。此时滑动 \(a\) 和 \(c\),分别假设 \(a\) 的区间是 \([m, n]\),\(c\) 的区间是 \([u, v]\),那么 \(c\) 的取值范围是 \([\max(u, m - b + 1), \min(n + b, v)]\)。只要这个集合不是空集就存在合法答案。此时我们枚举可得 \(b\)、\([m, n]\) 和 \([u, v]\) 的值。
但是这样太慢了,我们考虑优化。我们注意到 \([l_{i, 2}, r_{i, 2}]\) 中间的每一个 \(x\) 都会产生 \(r_{i, 1}\) 的贡献,对于 \([1, l_{i, 2} - 1]\) 中的每一个 \(u\) 可以产生 \(l_{i, 1}\) 的贡献,对于 \(v\) 可以产生 \(r_{i, 1}\) 的贡献;对于 \([r_{i, 2} + 1, 10^9]\) 的 \(m\) 会产生 \(l_{i, 1}\) 的贡献,对 \(n\) 会产生 \(r_{i, 1}\) 的贡献。这个和前缀和类似,我们不妨前缀和差分优化即可。复杂度 \(O(n \log n)\)。
思维难度:蓝;代码实现:蓝;实际:青。

P14984 [USACO26JAN1] Lineup Counting Queries P。
瞪眼法即可。
我们首先考虑这个东西貌似是类似于前缀和的东西,也就是说这个满足前缀和的性质,所以我们计算在时刻 \(t\) 的前 \(m\) 位置的答案。
然后我们打表发现每一次后 \(\frac{t}{2}\) 个位置都没有变!然后我们把数据范围开大,会发现它其实出现了一个斜着样子的东西,所以每次我们递归可以回到前面一个的位置!这个位置我们瞪眼即可。但是有一些数字就不再会出现了,所以我们瞪眼发现第一个数字其实是 \(\frac{t}{3} + 1\)!这个结论很强,个数我们发现其实是两个一跳,两个一跳,所以总共有的数量我们也可以瞪出来!最后统计答案就行。
思维难度:?(我不好评价);代码实现:橙;瞪眼难度:紫;实际:紫。

P6772 [NOI2020] 美食家。
很好的拼好题。
首先我们考虑暴力 DP。自然地,我们设 \(f_{u, i}\) 表示到达 \(u\) 节点且现在是第 \(i\) 天的最大答案。考虑转移:\(f_{v, i + w} = f_{u, i} + c_v\),关于 \(k\) 个庆祝活动我们只需要特殊处理一下即可。
我们观察到 \(n\)、\(m\) 和 \(w\) 的范围都很小啊,但是 \(T\) 的范围却大的惊人。我们不妨考虑矩阵优化一下。但是矩阵我们一般都是转移到 \(i + 1\),这个 \(i + w\) 怎么处理?因为 \(w \le 5\),我们考虑拆点,把一个 \(u\) 拆成 \(5\) 个,对于同一个 \(u\) 之间边权为 \(0\),对于一条边 \((u, v, w)\) 我们就从 \(u_w\) 向 \(v_1\) 连边即可。这样我们就构造出了矩阵,对于矩阵进行矩阵进行矩阵快速幂即可。这部分可以处理 \(k = 0\)。
接下啦考虑如何处理 \(k > 0\) 的情况。因为这个存在时间的先后顺序,我们不妨把 holidays 按照时间进行排序,从前往后处理。对于 \(t_i\) 和 \(t_{i - 1}\),我们不妨设 \(g_i\) 表示对于第 \(i\) 个庆祝活动的答案。很明显,我们考虑 \(g_i = g_{i - 1} \times G^{t_i - t_{i - 1}}\),然后在对应位置上加上 \(y_i\) 即可。但是如果直接这么做还是过不了,我们考虑对于 \(t_i - t_{i - 1}\) 进行二进制拆位计算,我们只需要预处理出来 \(2\) 的整数次幂的 \(G\) 即可。
最后我们考虑如果时间 \(t_{k} \ne T\),那么非常简单,我们只需要再进行 \(T - t_k\) 次矩阵快速幂。
最后判定答案输出。
思维难度:蓝;代码实现:蓝;实际:蓝。

P2519 [HAOI2011] problem a。
不太清楚这题和计数 DP 是如何挂上钩的......
但是还不错的题。首先,我们把问题转化一下,第 \(i\) 个人的排名是 \(a_i + 1\),所有和他同分的人的区间是 \([a_i + 1, n - b_i]\)。然后我们考虑什么情况一定不合法,如果 \(a_i + 1 > n - b_i\),说明根本没有放得进去的,所以不合法,剔除掉这种情况。我们考虑对于相同的区间进行合并,也就是我们维护 \(l_i\)、\(r_i\) 还有 \(tot_i\) 即可。对了,\(tot_i\) 要和 \(r_i - l_i + 1\) 这个取一个 \(\min\),因为满足条件的至多有 \(r_i - l_i + 1\) 人。然后我们考虑 DP。我们设 \(f_i\) 表示以 \(i\) 这个区间作为结尾的答案。我们二分到第一个 \(r_{pos} < l_i\) 的,然后 \(f_i = \max (f_{i - 1}, f_{pos} + tot_i)\)。最后答案再用 \(n\) 减去即可。
思维难度:青;代码实现:绿;实际:青。

P2267 琪琪的项链。
不是很难的计数 DP。
首先我们思考一下,这个是一个序列,如何去重呢?也就是说,我们现在有一个 \(a_i\),我们这个接在哪些序列后面即为合法?我们充分发扬人类智慧,注意到 \(a_i\) 的上一个位置(假设叫做 \(pos\)),那么所有以 \([pos, i - 1]\) 这些数字结尾的序列一定合法。正确性显然。我们思考,以 \([1, pos - 1]\) 这些数字为结尾的序列再加上一个 \(a_i\) 一定不合法,因为我们既然可以加上 \(a_i\),同理也一定可以加上 \(a_{pos}\),这是显然的。
所以我们设 \(f_i\) 表示以 \(i\) 结尾的序列个数,则 \(f_i = \sum_{lst_i \le j \le i - 1} f_j\)。这个使用前缀和维护即可。关于 \(a\) 的值域,其实我们直接离散化一下再统计即可。
思维难度:青;代码实现:黄;实际:青。

P1772 [ZJOI2006] 物流运输。
首先,我们需要充分理解题意。
题目中肯定含有和最短路有关的东西,所以我们设 \(days_{i, j}\) 表示从 \(i\) 天到 \(j\) 天一直选择一条路径的答案。如果不存在设为正无穷。接下来我们设 \(f_i\) 表示从第 \(1\) 天到第 \(i\) 天的答案。我们枚举一个 \(j\),表示我们从 \(j\) 天我们就开始换成一个新的路线,也就是 \(days_{j, i}\),然后前 \(j\) 天的答案就是 \(f_{j - 1}\),转移的成本是 \(k\)。也就是说:\(f_i = \min f_{j - 1} + days_{j, i} \times (i - j + 1) + k\)。
思维难度:青;代码实现:青;实际:青。

P11301 [NOISG 2021 Finals] Password
个人感觉很不错的反悔贪心!
我们先考虑每一个位置如果直接操作的话的答案应该是 \(d_i = b_i - a_i\),我们不妨设 \(w_i = d_i + (k + 1) \times t_i\),这样的话不会影响最终结果的局面,而是会影响操作次数。
我们根据积木游戏的结论,知道在第一开始的情况下 \(ans = \sum \max(0, d_i - d_{i - 1})\),所以我们不妨维护一个差分序列:\(e_i = d_i - d_{i - 1}\)。在这种情况下,我们假设对于 \([L, R]\) 区间范围内的所有点进行 \(k + 1\) 次操作,对应的差分序列会变成 \(e_L + M\) 和 \(e_{R + 1} - M\)。我们发现这种情况当且仅当 \(e_L < 0\) 同时 \(e_{R + 1} > 0\) 的情况。于是乎我们从后向前贪心,维护一个大根堆,每次操作 check 以下能否更优即可。
思维难度:青;代码实现:黄;实际:青。

P2768 珍珠项链。
先考虑朴素版 DP。我们不妨设 \(f_{i, j}\) 表示前 \(i\) 个位置,现在使用了 \(j\) 个元素,那么我们得出状态转移方程:\(f_{i, j} = f_{i - 1, j} \times j + f_{i - 1, j - 1} \times [k - (j - 1)]\)。考虑如何优化这个东西。
我们注意到这个其实也可以使用矩阵,满足矩阵的性质,最后矩阵只需要多维护一个 \(ans_i\) 表示现在的答案,然后跟着一起转移即可。
思维难度:青;代码实现:黄;实际:青。

posted @ 2026-10-12 16:33  Bob1108  阅读(11)  评论(0)    收藏  举报