题目记录(Before NOIP2025 ver)

T1. Beautiful Sequence Unraveling

定义 \(dp_{i,j}\) 表示长度为 \(i\),值域在 \([1,j]\) 之间的好序列的个数。发现好序列不好刻画,所以转化为所有序列的数量减去不是好序列的数量。前者很显然,即 \(i^j\)。接下来考虑后者怎么求。

考虑一个不好的序列 \(a\),假设 \(p\) 为最后一个 \(\max(a_1,a_2 \cdots,a_p) = \min(a_{p+1},a_{p+2},\cdots,a_n)\) 的位置,那么我们有一个重要的观察就是 \(a_{p+1},a_{p+2},\cdots,a_n\) 一定是一个好序列不然 \(p\) 就不是最大的。那么我们可以直接枚举位置 \(p\)\(a_p\) 的值 \(m\) 就可以了:

\[dp_{i,j} = j^i - \sum^{i-1}_{p=1}\sum^j_{m=1}(m^p - (m-1)^p)(dp_{i-p,j-m+1} - dp_{i-p,j-m}) \]

使用前缀和优化后可以做到 \(n^3\)

那么接下来考虑设 \(g_i\) 表示长度为 \(n\) 的序列,值域为 \([1,i]\) 的好排列数量,则我们有递推式:

\[g_i=dp_{n,i} - \sum^{i-1}_{j=1}\dbinom{i}{j}g_j \]

那么答案就是 \(\sum^n_{i=1} \dbinom{k}{i}g_i\)

T2. Lockout vs tourist

太牛了!

看到 \(n \le 22\),考虑使用状压 dp。此时设 \(m = |S|\),其中第 \(i\) 题的分数为 \(a_i\)\(S\) 去掉 \(i\) 后的期望最大的分为 \(b_i\),Tourist 有 \(p_i\) 的概率选择第 \(i\) 题,那么期望最大的分就是:

\[\max(p_i \times b_i + (1 - p_i) \times a_i) \]

考虑去二分答案 \(C\),那么我们现在就是需要找到一个 \(p\) 使得所有的 \(a_i + (b_i - a_i)p_i = C\)\(\sum p_i = n\)。那么此时考虑定义 \(d_i = \frac{C - a_i}{b_i - a_i}\),那么如果 \(b_i > a_i\) 则有 \(p_i \le d_i\) 否则 \(p_i \ge d_i\)。由于至少存在一个 \(b_i < a_i\),那么我们可以将判断条件改写为 \(\sum_{b_i < a_i}\max(0,d_i) \le 1\)\(\forall i(b_i \ge a_i),C \ge a_i\)

其实条件 \(2\) 只是给 \(C\) 定了一个下界,我们还是考虑条件 \(1\):我们注意到由于 \(b_i < a_i\),所以当 \(d_i > 0\) 的时候,\(C < a_i\),所以在这里我们只需要考虑所有大于 \(C\)\(a_i\)。这也告诉了我们 \(\sum \max(0,d_i)\) 其实是一个关于 \(C\) 的分段一次函数。那么我们其实可以直接去掉二分,直接在分段后在每一段上求一个最值就可以了,复杂度为 \(\mathrm O(n2^n)\)

T3. 巴蜀中学 NOIP 模拟赛 旋转

你发现有一些点是必须删的,比如 \((x_i,y_i)\)。那么我们定义一个格子 \((x,y)\) 是可选择的当且仅当 \((x,y)\) 是一个合法格子且 \((x,y)\) 不是必须删的。

考虑一次对于 \((x,y)\) 的操作,检查 \((x,y)\) 的左右两边的格子:

  • 两个格子都是可选的,则在两个格子间连一条无向边。
  • 恰一个格子是可选择的,在这个格子上连一个自环。
  • 否则无解。

现在考虑给无向边定向,代表指向的格子被这次操作选择。那么我们的任务就是所有格子的入度均不超过 \(1\) 的方案数,然后对于每一个连通块大力分讨即可。

T4. [湖北省选模拟 2023] 棋圣 / alphago

牛题。

假如图不是一个链,那么肯定能使得所有棋子都在一条边的两个端点上。于是考虑记两部分棋子黑白棋子颜色分别为 \(c(a/b)(0/1)\)。由于两部分棋子在一条边上,所以考虑二分图。

假如是二分图,那么不管怎么走两部分棋子所在的颜色都是不同的,那么最有情况还是两部分点中间有一条边权最大的边,则答案为 \(w_{max} \times (c(a)(0) \times c(b)(1) + c(a)(1) \times c(b)(0))\)。假如不是二分图,那么一定有一个奇环,通过这个奇环,我们可以把两部分的黑白颜色的棋子全部合起来,则答案为 \(w_{max} \times (c(a)(0)+c(b)(0))\times (c(a)(1)+c(b)(1))\)

接下来考虑图是链的情况。然后我们发现棋子的位置需要满足一下几个条件:

  • 在链上相邻的两个点操作完的距离 \(\le\) 两个点的初始距离。
  • 在链上相邻的两个点不会在操作中调换顺序。
  • 在链上的点的距离和操作前的距离在模 \(2\) 意义下同余。

然后定义 \(dp_{i,l,r}\) 表示到链上的第 \(i\) 个节点且这个点上有编号为 \([l,r]\) 的棋子的最大权值,然后直接转移即可,最后复杂度为 \(\mathrm O(n^4)\)

T5. EGOI 2025 D2T4

很牛的题目!

\(\text{Sol 1. n-1 bit}\)

这个是充分简单的,对于每一条边我们可以考虑用一个 \(0/1\) 字符表示删除编号较大/较小的那个点。

\(\text{Sol 2.}\) 菊花图

可以只用一个字符来表示第一条边中编号较大的点为中心点还是较小的点为中心点。然后之后的每一条边我们都知道了哪一个是叶子节点。

\(\text{Sol 3.}\)

同样可以只用一个字符来表示第一条边中哪一个是叶子节点,之后的每一条边都可以知道哪一个是叶子了。

\(\text{Sol 4. } 2\log_2 n+1 \text{ bit}\) 有链的菊花

考虑使用 \(\log_2 n\) 个字符来告诉我们有多少条链,然后再用 \(\log_2 n\) 个字符来表示这些链中有多少条的最后一条边的叶子节点的编号大于非叶子节点的编号。

然后我们就可以将所有的链从这棵树上删掉了,剩下一个菊花图,这个直接用 \(\text{Sol 2}\) 的方法即可,所以是 \(2 \log_2 n + 1\) 个字符。

\(\text{Sol 5. 7 bit}\) 有链的菊花

考虑将所有连接着叶子的边分为三组:

  • 长度为 \(1\) 的路径的最后一条边。
  • 属于长路径的最后一条边且叶子的编号小于另一端的编号。
  • 属于长路径的最后一条边且叶子的编号大于另一端的编号。

对于每一个集合,考虑使用一个字符来表示是否为空。然后考虑按照集合的大小排序,然后考虑用两个字符来传达是上面三种集合中的哪一个。

  • 假如是长度为 \(1\) 的集合,那么我们再传一个字符,其意义和菊花图的意义相同。
  • 假如为长集合,我们也像之前一样移除路径的大部分即可。

然后我们对于剩下的两组再做一遍,这里只需要传一个字符即可。同时我们可以注意到,当第一条新边与之前的叶子边相比更小时,我们就切换到了一个新的集合,而同一集合内的边则不会这样。

注意我们还需要知道叶子的中心节点是什么,所以假如我们前面没有额外传,那么我们再最后一次还需要额外传一次中心节点是什么。

\(\text{Sol 5. 2 bit}\)

令这棵树直径的中点为根,假如直径是一个偶数,那么就有两个根。同时称这条路径的一半为起始路径,另一半为标记路径。

我们逐层移除叶子,从最深的一层开始。在每一层,我们首先移除所有连接到起始路径的叶子。因为每一层上至少有一个叶子和起始路径不相连,所以这样会告诉我们合适去删上一层。接着我们还会将和标记路径相连的叶子节点删除。

对于本层剩余的叶子,我们考虑将叶子分为大叶子和小叶子并根据标记路径叶子在该层中的位置来编码哪个集合是第一个。

我们剩下的任务是识别起始路径和标记路径以及从最深层移除叶子,此时我们用两个字符来编码来用前两条边分别去识别起始路径和标记路径。最后,为了移除最后一层上的剩余叶子,我们像在其他层中一样进行,使用两个起始和标记边的顺序来编码第一组边是叶子节点的编号更小还是更大。

\(\text{Sol 6. 1 bit}\)

只用一个字符来表示第一条边切哪一个节点,然后考虑构造一种方案使得可以得到 \(l\)。那么玩家 \(2\) 将会遵循以下规则:

  • 如果当前边与最后移除的边相交,那么和菊花图类似,删掉不共的那个点。
  • 如果边中的一个节点此前有一条边被删了,则删掉两个节点中最近被删的那个点。
  • 否则与最后一条边进行比较。如果这条边比前一条大,那么它具有相同的类型,否则,它具有相反的类型。

那么根据如上的删除方法,叶子的删除顺序应为:

  • 如果在当前层上,有更多的叶子连接到与刚刚移除的叶子相同的节点上,则移除其中一个。
  • 如果我们在第一层,选择一个最大的不共享父节点的叶子集合,并将它们按类型分为两组。然后,使用一个可用的比特来传达第一条边的类型,并像往常一样进行。
  • 如果这是当前层的第一个叶子,选择任何一片不与前一层最后移除的叶子相连的叶子。
  • 否则,移除任何叶子。

而此时玩家 \(1\) 就可以做出正确 \(l\) 了,至此这题解决。

T6. CF1129E

先问 \((\{1\},\{2,3,4,\cdots ,n\},i)\) 然后就可以得到所有点的子树大小了。那么现在的问题就是求每一个点的父亲是什么。

假设目前叶子节点的集合为 \(S\),同时设 \(k = |S|\)。假设现在考虑到了第 \(i\) 个点,那么我们先问一边 \((\{1\},\{S_1,S_2,S_3,\cdots,S_k\},i)\),然后我们就知道他的儿子个数了然后二分去求出每一个儿子的位置,具体的找到最小的 \((\{1\},\{S_1,S_2,\cdots,S_p\},i)\) 大于 \(0\),然后重复这个操作 \(k\) 次即可。重复完之后把这个节点的所有儿子节点从 \(S\) 中删除,然后将这个点加入 \(S\) 即可,次数大概为 \(2n+2n\log n\) 次。

T7. CF1147E

先考虑 \(a_i \neq a_{i+1}\) 的情况。

我们发现我们只需要问一次 \((1,3)\) 就可以知道 \(3\) 的颜色,问一次 \((2,4)\) 就可以知道 \(4\) 的颜色。所以我们考虑先问一遍 \((1,3),(2,4),(5,7),(6,8) \cdots\),然后再问一遍 \((3,5),(4,6),(7,9),(8,10)\cdots\) 即可知道所有点的颜色。

那么此时考虑将所有相邻且颜色相同的点缩成一个连通块,即询问 \((1,2),(3,4),(4,5)\cdots\),然后再询问一边 \((2,3),(3,4),(4,5)\cdots\) 即可。

那么我们只需要 \(4\) 次就可以将这个问题解决。但是实际上 \(5\) 次更好写。

T8. P9601

最极限的一集。

考虑维护两个连通块中最长的链 \(A,B\),现在考虑新加入一个点 \(i\)。那么我们为了确定加入 \(i\) 之后的两条链的形状我们需要问 \(i\)\(A\) 的结尾节点和 \(i\)\(B\) 的结尾节点。假如两个均为 \(1\) 那么将两条链变成 \(A-i-B\) 这一条链,如果两个均为 \(0\) 那么将两条链变为 \(A-B\),同时加入一条只有一个节点的新链 \(i\)。假如一个 \(1\) 一个 \(0\) 那么将 \(i\) 连上去即可。

然后再看 \(A,B\) 两条链之间的连边情况。先在 \(B\) 上面二分去找到第一个和 \(A\) 中的点有连边的点,然后对于 \(A\) 做同样的操作,只不过我们这一次找最后面的一个点。

那么操作数是 \(2n + 2\log n\) 的,需要优化。

下面是最神秘的。

我们考虑每一次去加入 \(i\)\(i + 1\),假如我们考虑去询问 \(A\) 的末尾节点和 \(i\) 的情况,\(B\) 的末尾节点和 \(i\) 的情况和 \(i + 1\)\(i\) 的情况。那么会有以下几种情况,下面没有有边就是没边:

  • \(A\)\(i\) 有边,\(i\)\(i + 1\) 有边:\(A\) 变为 \(A - i - i + 1\)
  • \(B\)\(i\) 有边,\(i\)\(i + 1\) 有边:\(B\) 变为 \(B - i - i + 1\)
  • \(A\)\(i\) 有边,\(B\)\(i\) 有边,\(i\)\(i + 1\) 有边:\(A\) 变为 \(A - B\)\(B\) 变为 \(i - i + 1\)
  • \(A\)\(i\) 有边,\(B\)\(i\) 有边:\(A\) 变成 \(A - i - B\)\(B\) 变成 \(i + 1\)
  • \(A\)\(i\) 有边:则必有 \(B\)\(i + 1\) 有边所以 \(A\) 变成 \(A - i\)\(B\) 变成 \(B - i + 1\)
  • \(B\)\(i\) 有边:则必有 \(A\)\(i + 1\) 有边所以 \(A\) 变成 \(A - i + 1\)\(B\) 变成 \(B - i\)
  • 假如全部都没有边:\(A\) 变成 \(A - i + 1 - B\)\(B\) 变成 \(i\)

那么我们只需要 \(3\) 次询问就可以知道两个点和 \(A,B\) 的关系了,所以询问次数就变成了 \(\frac{3}{2}n + 2 \log n\)

T9. CF750F

抽象大了。

首先随便问一个点,假如回答的点的数量是 \(2\) 那就直接结束,否则就直接 \(dfs\),但是你发现这个东西需要 \(21\) 次。此时你发现如果你离根节点非常近然后继续 \(dfs\) 肯定不优秀,所以考虑去记录我当前的深度,然后假如离根节点的距离 \(\le 2\),那么直接 \(bfs\),此时你的 \(bfs\) 需要问 \(7\) 个点再加上前面 \(dfs\) 需要问的 \(10\) 个点是 \(17\) 个点,然而此时你发现如果你问了 \(6\) 个点都没出根结点的话那就直接输出剩下那一个节点即可,所以询问次数就是 \(16\) 次。

T10. P9266

\(dp_{i,j}\) 表示前 \(i\) 个数分成了 \(j\) 段的最小代价,那么转移就是:

\[dp_{i,j} = \min_{0 \le k < i} \{dp_{k,j-1} + c(k+1,i)\} \]

复杂度是 \(\mathrm O(n^2 k)\) 的,不能接受。此时你发现 \(c(l,r)\) 好像满足四边形不等式即 \(c(l,r)+c(l-1,r+1)\ge c(l,r+1)+c(l-1,r)\)。那么可以直接把 \(c(l,r)\) 预处理下来然后 \(\mathrm O(n^2)\) 做。但是还是不行。

你发现你好像无法优化转移了,此时你又发现他要求你选 \(k\) 个,你又想到有一种东西叫做 wqs 二分。然后你随便推了一推发现 \((1,dp_{i,1}),(2,dp_{i,2}),\cdots,(m,dp_{i,m})\) 是一个凸包,所以我们真的可以去掉第二维!那么现在的转移式就是:

\[dp_i = \min_{0 \le j < i} \{dp_j + c(j+1,i)+v\} \]

其中的 \(v\) 是你二分的值。又因为 \(c(i,j)\) 满足四边形不等式,所以我们可以用 CDQ 套分治去维护决策单调性。这个是 \(\mathrm O(n \log^3 n)\) 的。


但是 \(3\)\(\log\) 太不优美了,所以考虑更优美的做法。套路的将字符串转为 \(+1-1\) 数列,然后求前缀和。我们发现一个字串 \(s[l:r]\) 是合法的当且仅当 \(S_{l-1} = S_r = \min \limits^r_{i=l-1} S_i\)

看到了这个 \(\min\) 那么考虑去建初广义笛卡尔树每一个节点 u 对应着一个管辖区间 \([l,r]\),一个集合 \(s\) 对应着这个区间最小值的所有位置,以及它的儿子也就是最小值的所有位置划分出来的子区间。对于一个管辖 \([l,r]\) 的节点,对于他的询问 \(c(L+1,R)\) 的贡献可以被写成一下 \(5\) 种:

  • \(l \notin [L,R],r \notin [L,R]\):贡献为 \(0\)
  • \(l \in [L,R],r \in [L,R]\):贡献为 \(\dbinom{|s|}{2}\)
  • \(L \in [l,r],R \notin [l,r]\):贡献为 \(\dbinom{\sum_{i\in s} [i \ge L]}{2}\)
  • \(L \notin [l,r],R \in [l,r]\):贡献为 \(\dbinom{\sum_{i \in s}[i \le R]}{2}\)
  • \(L \in [l,r],R \in [l,r]\):贡献为 \(\dbinom{\sum_{i \in s}[L \le i \le R]}{2}\)

但是 wqs 二分肯定不能变,所以转移时不需要关心切了具体多少刀,然后定义 \(g_u\) 表示在 \(u\) 的子树至少切了一刀的贡献。假设我们切了 \(k\) 刀,其中第 \(p\) 刀的位置在 \(i_p\),那么贡献就是:

\[cost(l,i_1,3) + \sum_{j=1}^{k=1} cost(i_{j},i_{j+1},\{1,2,3,4,5\}) + cost(i_k,r,4) \]

当我们在 \(u\) 合并两个区间的时候,则只需要考虑第 \(5\) 种贡献。但是你发现有一些子树是不会被切的,所以我们再定义 \(dp_{u,i}\) 表示在 \(u\) 这个子树中,\(v_i\) 这个子树内必定切了一刀,前 \(i\) 棵子树的总贡献,那么转移就是:

\[dp_i = \min^{i-1}_{j=0} (0,dp_j+g_{v_j}+sum_{j}-sum_{i-1}+\dbinom{pre_i-pre_j}{2}) \]

然后你发现这个式子可以斜率优化,所以最后的复杂度为 \(\mathrm O(n \log n)\)

T11. CF2096G

给每个数设置一个不同的三进制值,使得删掉任意一个位后依然不存在相同数,要使位数尽可能少。由于我们可以删任意一位,相当于知道任意 \(T−1\) 个位就可以推出来不知道的位,那么这种结构直接用和模 \(3\)\(0\) 就行了。

T12. P11834

定义 \(U = \{1,2,3, \cdots ,n\}\)


考虑从 C 性质入手。

因为所有的边权全部都一样,所以只需要存在外向生成树即可。而我们发现所有可能成为这棵外向生成树的根节点的节点一定组成整张图唯一一个入度为 \(0\) 的 SCC。

考虑将求概率转化为求方案,最后乘上 \(2^{-2m}\) 即可,则设 \(dp_S\) 表示表示集合 \(S\) 恰好是缩点后唯一入度为 \(0\) 的 SCC 方案数,则答案为 \(\sum dp_S\)

首先我们需要保证 \(S\) 是一个 SCC,则设一个集合 \(S\) 组成一个 SCC 的方案数为 \(f_S\),这一部分就是主旋律。考虑使用总方案数减去不符合的方案数,即减去 DAG 的数量。

此时考虑使用 DAG 计数的方法每一次删去入度为 \(0\) 的 SCC,那么考虑定义 \(g_S\) 表示将 \(S\) 分割成为若干个入度为 \(0\) 的方案数,那么容斥系数就是 \((-1)^{k + 1}\) 其中 \(k\) 为 SCC 的数量。而此时考虑将容斥系数放到 dp 当中方便转移。则我们就有转移:

\[g_S = f_S - \sum_{T \subseteq S,\text{lowbit(S)} \in T} f_Tg_{S-T} \]

那么 \(f_S\) 的转移就是去枚举入度为 \(0\) 的 SCC \(T\),然后 \(T\) 可以向 \(S-T\) 连边,\(S-T\) 之间可以互相连边,则转移就是:

\[f_S = 4^{E(S,S)}-\sum_{T \subset S}g_T2^{E(T,S-T)}4^{E(S-T,S-T)} \]

其中 \(E(S,T)\) 表示 \(S\)\(T\) 的边数。由于 \(E(S,S)\) 是好算的,又因为 \(E(S,T) = E(S + T,S + T) - E(S,S) - E(T,T)\),所以 \(E(S,T)\) 可以在 \(\mathrm O(2^nn)\) 的时间内求出。

最后考虑计算 \(dp_S\),考虑枚举 \(T \in U - S\) 中存在若干个入度为 \(0\) 的 SCC,那么 \(S+T\)\(U-S-T\) 之间可以任意连边,\(U - S - T\) 可以互相连边。而我们发现这个容斥系数为 \((-1)^k\) 也就是 \(-g_T\),则我们有转移:

\[dp_S = \sum_{T \subset U-S} -f_Sg_T2^{E(S+T,U-S-T)}4^{E(U-S-T,U-S-T)} \]

那么我们就可以在 \(\mathrm O(3^n)\) 的时间内解决 C 性质。


通过模拟 Kruskal 的过程,我们发现对于任意的 \(w\),图 \(G\) 的所有最小生成树在保留所有 \(\le w\) 的边的连通性是相同的。那么我们就有一种判断方式来看这张图是否合法:

  • 从小到大去枚举 \(w\),维护目前所有连通块中可能成为根的点集,每一次加入所有权值为 \(w\) 的边然后更新可能成为根的点集,到了最后如果可能成为根的点集不为空则合法。

考虑可能成为根的点集如何合并。我们称一条边为关键边当且仅当其终点属于根集。那么每一次合并的时候显然只需要保存所有关键边,这些关键边应当存在连通块之间的一棵外向生成树。那可能成为根的点就是可能成为连通块之间外向树的根对应的连通块中可能成为根节点的点集之并。

那么这个问题现在就很像 C 性质了。此时考虑定义 \(ext_S\)​ 表示集合 \(S\) 所处原本连通块集合的并;\(cof_S\) 表示保证 \(S\) 分别为原本每个连通块可能成为根的点集情况下任意连边的总方案数;\(ent_S\) 表示合并连通块后集合 \(S\) 所处连通块集合;\(f_S\) 表示 \(S\)\(ext_S\) 中可能成为根的节点的方案数;\(g_S\) 表示将 \(S\) 在新图上划分为若干个 0 入度 SCC 方案数;\(dp_S\) 表示 \(S\)\(ent_S\) 中可能成为根的节点的方案数。

因为 \(ext_T\)\(ext_{S-T}\) 之间可以连非关键边,则我们有:

\[g_S = f_S - \sum_{T \subseteq S,\text{lowbit(S)} \in T} ok(T,S - T) f_{T}g_{S - T} + 2^{D(S,S - T)} \]

同样的考虑将容斥系数塞进 \(g_S\) 方便后面计算。其中 \(ok(S,T)\) 表示在新图上 \(ext_S \cap ext_T = \varnothing\)\(D(S,T)\) 表示可能成为根的集合为 \(S,T\) 的情况下,\(ext_S,ext_T\) 之间的非关键边,\(D(S,T)\) 可以通过:

\[D(S,T) = E(S,ext_T - T) + E(ext_S - S,T) + E(ext_S - S,ext_T - T) \times 2 \]

得出。

\(T = ext_{\text{lowbit(S)}} \& S\),则 \(cof_S\) 可以通过:

\[cof_S = cof_{S - T} dp^{\prime}_T 4^{E(est_S - T,est_T)} \]

得出。那么我们就有 \(f_S\) 的转移式:

\[f_S = cof_S - \sum_{T \subset S} ok(T,S - T)g_T cof_{S-T}2^{E(est_T,est_{S-T}) + E(est_{S-T},est_T-T)} \]

接下来考虑 \(dp_S\) 的转移,假设 \(U = ent_S,A = U - ext_{S+T}\),而 \(A\) 之内可以任意连边,设其方案数为 \(con_S\),那么我们考虑分成两类来转移:

  • 对于每个原本的连通块:\(con_S = \sum_{T\subset S} dp^{\prime}_T\)
  • 对于若干个原本连通块的并:设 \(T = ext_{\text{lowbit}(S)}\),则 \(con_S = con_Tcon_{S-T}4^{E(est_T,est_{S-T})}\)

由于 \(est_{S+T}\)\(A\) 之间和 \(est_{S+T}-S-T\)\(A\) 之间可以连边,则 \(dp_S\) 的转移式为:

\[dp_S = \sum_{T \subset S-T}-ok(S,T)ok(S,A)f_Sg_T2^{E(est_{S+T},A)+E(est_{S+T}-S-T,A)+D(S,T)} \]

那么最终答案为 \(\sum dp_S\)。注意到除了关键边和非关键边之外还有连通块内的边,这种可以直接给答案乘上 \(4\)

T13. P6624

套路的将 \(\gcd\) 拆开可得:

\[\begin{aligned} ans &= \sum_T(\sum^{n-1}_{i=1}w_{e_i})\times \gcd(w_{e_1},\cdots w_{e_{n-1}}) \\ &= \sum_T (\sum^{n-1}_{i=1}w_{e_i}) \times \sum_{d | w_1,d|w_2,\cdots ,d | w_{n-1}} \varphi(d)\\ &= \sum^V_{d=1} \varphi(d) \times (\sum_{T,d | w_1,\cdots ,d | w_{n-1}}\sum^{n-1}_{i=1} w_{e_i}) \end{aligned} \]

我们发现后面的式子实际上就是求所有边权均为 \(d\) 的倍数的子图的所有生成树的边权之和。那么考虑去拆贡献,那么对于每一条边我们要求的就是包含这条边的生成树数量,那么又可以将其转化为原图中的生成树数量减去原图去掉这条边后的生成树数量。对于每一条边都求一次就是 \(\mathrm O(mn^3)\),而外面还需要枚举因数,那么复杂度就是 \(\mathrm O(Vmn^3)\),直接爆炸。

我们发现这个求的是边权和的和而不是边权积的和,于是考虑将每一条边转化为一个多项式 \(wx+1\),而现在我们求得就是所有生成树的边权积的和了,而这个多项式中 \(x\) 的系数就是我们想要的东西。由于我们只需要知道 \(x\) 的系数,实际上就是这个多项式对于 \(x^2\) 取模后的结果,那么我们就可以用一个 pair 来维护这个多项式。

那么我们重新定义一下 pair 的运算:

  • 加法:两个数直接加即可。
  • 减法:两个数直接减即可。
  • 乘法:对于两个 pair\((a,b),(a_1,b_1)\),由于去掉了二次项的系数,则运算结果为 \((ab_1+a_1b,bb_1)\)
  • 除法:对于两个 pair\((a,b),(a_1,b_1)\),我们可以直接硬算,得到的结果为 \((\frac{a}{b_1}+\frac{a_1b}{b_1^2},\frac{b}{b_1})\)。由于模数是质数,所以可以直接求逆元。

但是复杂度是 \(\mathrm O(Vn^3)\) 的,依然无法通过。而我们注意到如果一个数 \(d\) 它的倍数在边权中出现了小于 \(n-1\) 次,那么我们是可以直接不用求得,因为这样子不可能有生成树。有了这个优化就可以通过了。

T14. P4370

首先所有可以选的组合数里面最大的一定是 \(\dbinom{n}{\frac{n}{2}}\),然后我们考虑使用广搜的方式去找接下来的 \(k-1\) 个数。但是我们现在就要比较两个组合数的大小,但是不能取模,因为取完摸之后再比较大小就不准确了。所以考虑对于所有的组合数取 \(\log\)

根据 \(\log\) 的运算规则,我们可以推出:

\[\log C^m_{n} = \sum^n_{i=1} \log i - \sum^m_{i=1} \log i - \sum^{n - m}_{i = 1}\log i \]

然后直接预处理 \(\sum \log i\) 即可。时间复杂度 \(\mathrm O(k\log k)\)

T15. qoj8335

先忽略 \(A_j\)\(B\),那么 \(f(x) = \oplus^m_{j=1} (X<<<s_j)\) 可以看作在 \(\mathcal{V}\) 上的线性变换,而线性变换可以用矩阵高效维护,那么考虑如何扩展矩阵形式从而维护本题。

此时来看与运算和或运算:

  • \(1 \vee x = 1,0 \wedge x = 0\)
  • \(0 \vee x = 1 \wedge x = x\)

那么如果 \(o_j = \vee\) 且对应位置是 \(0\) 或者 \(o_j = \wedge\) 且对应位置是 \(1\),那么矩阵不用变。

如果 \(o_j = \wedge\) 且对应位置是 \(0\),那么直接将矩阵的对应位置设为 \(0\) 即可。如果 \(o_j = \vee\) 且对应位置是 \(1\),那么把矩阵的对应位置设为 \(0\) 然后最后在 \(B\) 的这一位上异或上 \(1\) 即可。

本题中可以看成在 \(\mathbb Z_2\) 下进行矩阵运算,\(\oplus\)\(+\) 等价。

可以用仿射变换维护本题的操作。仿射变换可以按如下方式进行复合:

\[a^{\prime}(ax+b)+b^{\prime} = (a^{\prime}a)x+(a^{\prime}b+b^{\prime}) \]

那么用线段树维护区间内 \(a,b\) 的信息即可。然后存 \(64 \times 64\) 的矩阵 \(A\) 和长度为 \(64\) 的向量 \(B\),而我们注意到是在 \(\mathbb Z_2\) 下的运算,所以压位后用异或等位运算计算即可。

那么复杂度就是 \(\mathrm O(n\omega^2+q\omega\log n + c\omega^2\log n)\),其中 \(\omega = 64\)

T16. P5324

假设一个序列里面有 \(k_1\)\(n\)\(k_2\)\(n-k_1\)\(k_3\)\(n - k_1 - k_2\),以此类推,那么这个序列肯定可以被删空,那么 \(\sum k = n\)。所以我们现在的问题就是求出 \(n - \sum k\)

由于值域很小,所以考虑用一个线段树去维护数轴。如果一个数 \(x\) 出现了 \(c_x\) 次,那么数轴上 \([x - c_x + 1,x]\) 的位置全都是,那么我们要求的就是这个数轴上 \(0\) 的个数。

单点修改很简单,直接 \(\mathrm O(\log n)\) 去修改即可,而整体加或者减 \(1\) 可以去设置一个指针 \(s\),那么在现在这个坐标轴上的 \(x\) 在实际位置上实在 \(x-s\) 的,然后在移动的时候减掉一些没有贡献的点,即 \(s+n\),然后就行了。

查询的时候查询区间 \([s+1,s+n]\) 即可。

T17. P11150

注意到如果插在位置 \(i\),而有 \(t_j > s_{i+j}\) 那么这个方案肯定是不优的。

那么题目就是让你找到 \(s_{1,i}+t_{1,j-1}=s_{1,i+j-1}\)\(t_j < s_{i+j}\)\((i,j)\),然后你需要最小化 \(i+j\),然后最小化 \(t_{j,m} + s_{i+1,n}\),最后最小化 \(i\)

那么为了保证上面的条件一定有一个成立,那么我们可以在 \(s\) 的末尾处插入一个极大的字符。

由于 \(\sum |t| \le 10^6\),所以考虑去枚举 \(j\),然后找到最小满足条件的 \(i\)。现在要找的就是在 \(s\) 中查找 \(t_{1,j-1}\) 且下一位大于 \(c\)。但是这个很难直接做。

注意到字符集很小,那么考虑去枚举极大的 \(c > t_j\)\(s_{i+j} = c\),然后就直接在 \(s\) 里面去找最早出现的 \(t_{1,j-1} + c\) 即可。这个可以使用 SAM。

那么现在我们就有 \(\mathrm O(\min(10 \sum |t|,n))\) 种方案,考虑使用用哈希+二分找到第一个不同的位置,然后比较这个位置的字符大小。

同时我们还需要最小化 \(j\),但是在 SAM 上查出来的不一定是最小的。

要将 \(t\) 尽可能向左移且不改变方案形成的最终串。此时我们发现如果左移的长度 \(len\) 一定是 \(t\) 的周期的倍数。所以倍增向左移就可以了。


还有神秘 \(Z\) 函数做法。在此我们定义 \(A^{+\infty}\) 为将 \(A\) 拼接 \(+\infty\) 次。

考虑对于固定的 \(B\),考虑在 \(x,y\) 两处哪里插入更优。删掉公共前后缀后可以知道就是比较 \(B+A_{x+1,y}\)\(A_{x+1,y} + B\) 的字典序。而比较 \(A + B\)\(B + A\) 的字典序就是比较 \(A^{+\infty}\)\(B^{+\infty}\) 的字典序。

那么插入在 \(x\) 比插入在 \(y\) 更有当且仅当 \(B^{+\infty}\) 的字典序小于等于 \(A_{x+1,y}^{\infty}\),那么按照 \(B^{\infty}\) 的字典序大小来计算,那么答案是单调的,那么排完序后座决策单调性分治即可。那么我们现在的任务就是如何在 \(\mathrm O(|A|+|B|)\) 的时间内解决单组询问。

那么此时考虑如何高效的比较 \(B+A_{x+1,y}\)\(A_{x+1,y}+B\) 的字典序。那么接下来分两类讨论:

  • \(y-x < |B|\)

先比较 \(B_{1,y-x}\)\(A_{x+1,y}\) 的字典序,然后预处理 \(B + \texttt{\#} + A\)\(Z\) 函数之后就可以 \(\mathrm O(1)\) 去判断。如果还是相等的,那么我们去比较 \(B_{y-x+1,|B|}\)\(B_{1,|B|-(y-x)}\) 的字典序,这个还是可以 \(\mathrm O(1)\) 判断。如果依然相等,那么最后比较 \(A_{x+1,y}+B_{1,y-x}\)\(B_{|B|-(y-x)+1,|B|}\),此时依然可以 \(\mathrm O(1)\) 判断。

  • \(y-x > |B|\)

假设 \(A_{x+1,y}=B^k+C\),其中 \(B\) 不为 \(C\) 的前缀,那么 \(B+A_{x+1,y} = B^{k+1}+C,A_{x+1,y}+B=B^k+C+B\),那么就变成了比较 \(B+C\)\(C+B\),那么此时依然可以使用 \(y-x < |B|\) 的方法解决了。而 \(k\) 可以使用双指针求出。

\(B^{+\infty}\) 按照字典序排序直接用随机化+归并排序,这个复杂度是期望 \(\mathrm O(n \log n)\) 的。

T18. P9318

先考虑只有一排而不考虑锁不锁死的情况,那么很明显就是斐波那契数,由于还有高度,所以还要进行 \(m\) 次幂。

那么我们定义 \(dp_n\) 表示高度为 \(m\) 且有 \(n\) 列但是不一定锁死的方案数。

那么接下来考虑令 \(g_n\) 表示高度为 \(m\)\(n\) 列锁死了的方案数,那么考虑最后一个锁死的块的宽度为 \(i\),那么我们有转移式:

\[g_n = dp_n - \sum^{n-1}_{i=1}dp_{n-i}g_i \]

而这个是 \(\mathrm O(n^2)\) 的,和 \(m\) 无关,而又有 \(n \times m \le 5 \times 10^5\) 这个限制,所以考虑再设计一个 \(dp\) 来平衡复杂度

定义 \(dp_{i,j}\) 表示考虑了前 \(i\) 列,且在最后一列有 \(j\)\(1\times 2\) 的块。那么转移式就是:

\[dp_{i,j} = \sum^{m-1}_{k=1} \dbinom{m-k}{j} \times dp_{i-1,k} \]

那么答案就是 \(\sum dp_{n-1,i}\)。由于 \(k\) 不等于 \(0\) 也不等于 \(m\),所以一定是锁死的。而这个 dp 是 \(\mathrm O(nm^2)\) 的。

所以如果 \(n < m^2\) 的时候跑第一个 \(dp\),如果 \(n > m^2\) 的时候跑第二个 \(dp\),那么复杂度就是 \(\mathrm O((n\times m)^{\frac{4}{3}})\)

T19. P10896

假设这 \(n\) 个串是固定的怎么做。

假设 \(p_i\)\(q_i\) 为第 \(i\) 个串的左括号和右括号的数量,\(x_i\) 为把括号串视为网格图上的折线,起点与最低点的距离,\(y_i\) 为终点与最低点的距离。那么我们发现答案就是:

\[\sum^n_{i=1} \min(p_i,q_i) - \max^n_{i=1} \min(x_i,y_i) \]

那么考虑将其分为两部分别计算贡献。对于第一部分,直接考虑枚举有多少个左括号即可,那么答案为:

\[\sum^n_{i=1}\sum^{a_i}_{j=1} \min(a_i-j,j) \times \dbinom{a_j}{j} \times 2^{-a_i} \]

后者考虑去枚举 \(\max^n_{i=1} \min(x_i,y_i)\) 的值,就是 \(\sum_{k \ge 1} P(\max^n_{i=1} \min(x_i,y_i) \ge k) = \sum_{k \ge 1} (1-\prod^n_{i=1}(1 - P(\min(x_i,y_i) \ge k)))\)。那么考虑去枚举这个 \(i,k\),然后对于每一个 \(a_i\) 去计算 \(\min(x_i,y_i) \ge k\) 的方案数。

将最低点设为 \(0\),要求就是起点和终点都 \(\ge k\)。那么考虑去枚举起点和结束点,那么方案数就是经过 \(y = 0\) 的数量减去经过 \(y=-1\) 的数量,所以对于一对固定的 \(s,t\) 其答案为:

\[\dbinom{a_i}{\frac{a_i+s+t}{2}} - \dbinom{a_i}{\frac{a_i+s+t+2}{2}} \]

那么最终的答案就是:

\[\sum_{s \ge k}\sum_{t\ge k}[s+t+a_i \bmod 2 = 0]\dbinom{a_i}{\frac{a_i+s+t}{2}} - \dbinom{a_i}{\frac{a_i+s+t+2}{2}} \]

然后发现如果 \(s\) 是固定的,那么正负号抵消,所以答案就是:

\[\sum_{s\ge k}\dbinom{a_i}{\lfloor \frac{a_i + s + k+1}{2} \rfloor} \]

然后就可以直接算了。

T20. AT_nikkei2019_qual_f

因为每一个颜色都强制要选 \(2\) 个,所以考虑将每种颜色的最大值和次大值 \(a_i,a_j\) 变成两个 \(\frac{a_i+a_j}{2}\),正确性显然。

此时考虑如果可以多选一个,我们有那些策略:

  • 选择权值最大的且其颜色被选过 \(2\) 及以上的点。
  • 选择一个还未被选择的颜色并且选出其最大值和次大值然后扔掉单独选入中权值最小的点。
  • 扔掉一个只被选择过 \(2\) 次的颜色扔掉,然后再选择一个从未被选的颜色并选择这个颜色中权值最大的 \(3\) 个点。

所以考虑去维护两个 multiset 分别用于存储被单独选入的数和未被选入的数中权值最大的 \(3\) 个点的权值即可。

T21. CF1120F

好题。

假如第 \(i\) 封信被存在了巢穴里面,那么从此以后巢穴之中就一直会有一封信。所以现在考虑去枚举这个 \(i\) 的位置,然后再把 \(T \times (t_{n+1}-t_i)\) 的代价算上。那么之后的所有交替存储信的代价就是 \(0\) 了。接下来考虑如果巢穴里面已经有自己的信了该怎么办。

我们发现假如自己把这一封信放在巢穴当中那么他的代价就是当前时间减到下一次对方来取的时间,那么我们就可以计算这个代价是多少了,从而我们直接和直接送比较即可。

T22. CF1209H

好题。

考虑现将所有位置的速度都 \(+1\),那么平地也就等于一个速度为 \(1\) 的加速带了。

现在考虑将传送带从左往右依次考虑,假设当前加入的传送带长度为 \(x\) 速度为 \(y\)。那么现在现将速度设为最大,那么时间就要加上 \(\frac{x}{y+1}\),而能量也减少了 \(\frac{x}{y+1}\)

考虑让前面一个长度为 \(d\),初始速度为 \(v\) 的传送带速度减小 \(x\),那么这一段节省的能量就是:

\[\frac{d}{v-x} \times x = E \]

而我们现在就是确定了这个 \(E\) 的值是多少,那么我们需要求出降了 \(x\) 的速度对于答案的影响:

\[ans \gets ans + (\frac{d}{v-x} - \frac{d}{v}) \]

然后我们发现实际上就是:

\[ans \gets ans + \frac{E}{v} \]

然后我们惊讶地发现之和我们需要节省多少能量和速度有关,所以每一次节省能量直接选取速度最大的传送带即可。注意每个传送带能节省的能量是有上限的,以及处理当前传送带之前要把当前传送带也考虑进去,因为可能不够拿或者不优。

T23. AT_toyota2023spring_final_g

考虑去拆贡献,那么合并两个连通块就会将其中一个连通块内所有点的深度 \(+1\)。而这一次合并操作的代价就是该连通块未被添加的边数。那么考虑定义一个权值就是其内部未连边数,合并答案时的答案就是加上两个连通块的最大值,合并后的连通块的权值就是原本两个连通块的权值之和再 \(-2\)

为了方便,考虑将每个点的初始权值都设为 \(-2\),这样子合并就可以直接相加了,最后答案再加上 \(2n-2\) 即可。

随后发现一定是一个点一个点加到一个大连通块里最优。那么我们需要做的就是找一个根,然后按照顺序遍历到一个点就加到连通块里。

假设一个点再时刻 \(t\) 加入,那么答案就会加上 \(n - t\)。而不妨考虑将其改为加上 \(n - t + 1\),最后将答案 \(+2\) 即可。

假如现在有两个连通块 \(A,B\),其权值分别为 \(Aval,Bval\),权值和为 \(Asum,Bsum\),大小为 \(Asiz,Bsiz\),那么 \(A\)\(B\) 前面连边当且仅当:

\[Asiz + Asum \times Bsiz + Bsiz > Bval + Bsum \times Asiz + Asiz \]

改写一下发现就是:

\[\frac{Asum}{Asiz} > \frac{Bsum}{Bsiz} \]

于是直接用堆和并查集维护并计算贡献即可。

T24. P10432

非常好的观察性质题。

我们可以注意到如果 \(u\) 在最后是 \(v\) 的父亲,那么 \(h_u \le h_v\)。那么就考虑按照原本的深度逐层加点。

考虑定义 \(dp_{i,j,k}\) 表示假设我们目前已经考虑了高度 \(\le i\) 的节点,且当前的叶子节点有 \(j\) 个接口,我们将 \(k\) 个深度 \(\le i\) 的节点的深度调整为 \(i + 1\) 且还没有接入树中的最小代价。初始化就是 \(dp_{0,1,0} = 1\) 表示可以选一个根。

接下来考虑转移。首先加上 \(i + 1\) 高度上的原有的点,同时使用 \(k \times K\) 的花费将 \(k\) 个点的深度调整。同时我们有注意到 \(j\) 个在叶子节点上的接口肯定要尽早用完,因为用一个后它自己也会产生一个所以 \(j\) 不会变。那么延迟连边肯定会更劣。

所以假如我们加入了 \(cnt\) 个高度为 \(i + 1\) 的点,那么会有 \(\max(0,cnt + k - j)\) 个点的深度进行调整,所以转移式就是:

\[dp_{i+1,j,\max(0,cnt+k-j)} \gets dp_{i,j,k} + K \times \max(0,cnt + k - j) \]

第二种情况就是我们需要增加接口数量,我们又注意到那 \(k\) 个被抬高的点不应该在此处添加接口数量,因为如果他们需要添加接口数量那么交给他们原高度的节点去添加接口肯定更优。所以我们就需要使用 \(\min_{1 \le t \le n,h_t = i + 1}c_t\) 的代价来添加接口,而这个就是完全背包问题。

但是这样子直接做是 \(\mathrm O(Hn^2)\) 的,所以我们需要考虑对于第一维进行离散化。我们注意到因为每轮至少连入一个点,所以有用的高度只有将所有点从原先高度上向右依次排开的高度。

所以复杂度为 \(\mathrm O(n^3)\)

T25. qoj8542

我们定义合法序列为一个全 \(0\) 序列通过任意次操作后得到的序列。那么我们此时考虑序列 \(x\) 在什么情况下是一个合法序列。直接考虑不好考虑,于是我们可以反向考虑,将 \(x\) 逐步减为全 \(0\) 序列。

如果存在 \(x_i > x_{i+1}\),那么我们对于 \([1,i]\) 至少需要进行 \(x_i - x_{i+1}\) 此前缀减。如果存在 \(x_i < x_{i+1}\),那么我们对于 \([i + 1,n]\) 至少需要进行 \(x_{i+1} - x_{i}\) 次后缀减。

那么考虑先将所有满足 \(x_i > x_{i+1}\) 的位置 \(i\)\(x_i - x_{i+1}\)\([1,i]\) 前缀减然后再对于所有存在 \(x_i < x_{i+1}\) 的位置做 \(x_{i+1} - x_i\)\([i+1,n]\) 后缀减。显然在所有的操作过后 \(x_i\) 肯定都是相同的。如果此时 \(x_i\) 中所有元素均 \(\ge 0\),那么 \(x\) 就是一个合法序列,否则不是。

我们发现进行完所有操作后 \(a_0\) 减少了 \(\sum^n_{i=0} \max(0,x_i - x_{i+1})\),而 \(a_{n+1}\) 减少了 \(\sum^n_{i=0} \max(0,x_{i+1} - x_i)\)。考虑令 \(a_0 = a_{n+1} = inf\)。由于所有的 \(a_i\) 在最后都需要大于 \(0\),所以条件可以转化为:

\[\begin{cases} x_0-\sum_{i=0}^{n}\max(0,x_i-x_{i+1})\ge 0\\ x_{n+1}-\sum_{i=0}^{n}\max(0,x_{i+1}-x_i)\ge 0 \end{cases} \]

考虑将上下两个式子相加可得:

\[\sum_{i=0}^n |x_i-x_{i+1}| \le 2inf \]

而这就是 \(x\) 是一个合法序列的充要条件。

回到本题,我们发现花费 \(k\) 的代价对长度为 \(k\) 的前/后缀进行操作均摊到每一个元素的代价是 \(1\)。那么我们要求的就是最小的 \(\sum \limits^n_{i=1} y_i\)\(\sum \limits_{i=0}^n |y_i-y_{i+1}| \le 2inf\)。考虑令 \(F = \sum^n_{i=0} |y_i-y_{i+1}|\)我们每次可以选择一段极长的 \(y_l = y_{l+1} =\cdots = y_r\),满足 \(y_l < y_{l-1}\)\(y_{r} < y_{r+1}\),将区间 \([l,r]\) 整体 \(+1\)。将 \(y\) 看成柱状图的话,相当于 "填坑"。每填一层坑,\(F\) 都会 \(-2\),而我们耗费了 "坑的宽度" 这么多代价。于是,我们的策略肯定是:每次选择宽度尽可能小的坑来填。我们就这样不断填,直到条件成立。

T26. CF704C

注意到 \(k_i \le 2\),那么如果我们把所有的 \(\text{bool}\) 变量看做一个点的话,那么考虑将出现在同一组的两个变量 \(x,y\) 之间连一条边 \((x,y)\),那么每个点的度数将会小于 \(2\)。所以整一张图将会是一堆环、一堆链以及一堆孤立点。那么考虑对于每一个环,链分别跑一遍 dp。

对于一个链我们就设 \(dp_{i,j,k}\) 表示考虑到链上的第 \(i\) 个点,其值为 \(j\),所有布尔表达式的值异或起来为 \(k\) 的方案数。转移的时候直接枚举上一个点的值即可。

对于环就考虑定义 \(dp_{i,j,k,lst}\) 表示环上的第一个点是 \(lst\),然后我们最后就强制从 \(j=fst\)\(dp\) 计算答案即可。

最后我们再令 \(f_{i,j}\) 表示当前考虑了前 \(i\) 个链/环,这些连通块中所有表达式异或起来为 \(j\) 的方案数,这个同样直接枚举上一个值即可。所以转移复杂度是 \(\mathrm O(1)\) 的。

T27. CF1442E

我们肯定知道如果所有连在一起,颜色一样的点都可以一起删。

假设现在只有黑色或者白色,那么考虑将两端同色的边的权值设为 \(1\),否则为 \(0\)。假设此时的直径的长度为 \(len\),那么答案就是 \(\lceil \frac{len}{2} \rceil + 1\)

而灰点实际上就是需要给他染色,使得直径最长最小。那么考虑定义 \(dp_{u,0/1},g_{u,0/1}\) 分别表示 \(u\) 染成白/黑,子树中某个点离它最大的距离和 \(u\) 染成白/黑经过 \(u\) 的答案。然后直接转移即可。

T28. CF1458C

好题。

假如没有最后那两个操作肯定会,考虑维护两个 \(tag\) 分别表示横坐标的偏移量和纵坐标的偏移量即可。

接下来去观察那两个操作到底在干嘛。发现 \(I\) 操作实际上就是令 \(a^{\prime}_{i,a_{i,j}} = j\),我们发现实际上就是将 \(j\)\(a_{i,j}\) 换了一个位置,那么此时考虑讲一个位置 \(i,j\) 用一个三元组 \((i,j,a_{i,j})\) 表示。操作 \(I\) 就等于将 \(j\)\(a_{i,j}\) 在三元组中的位置交换,也就是变为 \((i,a_{i,j},j)\)。然后对于每一维我们只需要维护最后他被换到了那个位置即可。

posted @ 2025-09-24 13:26  sqrtqwq  阅读(22)  评论(0)    收藏  举报