让思维顺利成章:初尝试后的理论分析

· · 算法·理论

引言

我们在做依赖思维与所谓数学直觉的题目时,往往会被卡住,无数次问自己下一步该怎么办,盯着题干和样例发呆,手搓了几次样例后总觉得自己有感觉但偏偏就是想不出来怎么做。

没关系,我们今天从头来解决这个问题。通过例题讲解来串联思路框架的方式,让思维有起点,让思维有方向。由浅入深,一步一步来。

CF476D Dreamoon and Sets

我们很容易的就可以手玩明白样例,但是问题是样例 2 里面的 22 是怎么来的?

没关系,我们可以现来玩玩样例一。

样例一的特点是 k=1,出题人这么出一定有他的道理,就像 OI 赛制的题目会给特殊性质和小数据范围一步步引导你,就像高考数学卷子压轴题的前两小问对最后一问有引导性是一个道理。样例也可以作为引导,那么 k=1 开始就是分析问题的起点。

我们看看样例,样例给出的操作是 1,2,3,5 ,很不错,发现里面是没有 4 的。因为 24 不同时存在——都有因子 2。都有因子 2,也就是偶数不能同时存在。而三个连续自然数最少出现一个偶数,连续四个就会出现两个偶数,所以跳过去就好了,第四个数不连续即可,同时第一个数是奇数。

那么我们接着刚才的 1,2,3,5 往后写,就是 7,8,9,11 ,因为 6 是偶数不能作为开头。然后枚举三位后把第四位跳过,显然满足要求。

到此,k=1 我们已经顺利解决,接下来,如果 k>1 我们只需要给刚才的构造方案乘以 2 即可。这道题就解决了。

我们来梳理一下,我们是如何解决这个问题?从看起来比较简单的数据入手,开始试,然后得出结论。

这就叫做从初尝试起步,是一个完整的思考过程,而不是一眼瞪出答案。

接下来,我们来再看下一道题。

CF1430C Numbers on Whiteboard

我们依然使用上面题目的处理思路,先从尝试开始,先不考虑方案生成过程,直说结果。

$n=3$,可以生成 $2$ 和 $3$,答案是 $2 n=4$,就是样例,答案是 $2

我们大胆猜测,答案是 2

我们的标题是,初尝试后的理论分析,我们上一题虽然是试,但是并不涉及任何猜测过程,现在我们其实是在猜,那么我们就需要开始理性分析了。

首先,如何保证我们的答案是 2?我们可以将两个数相加除以二看作将两个数消成一个数,那要让剩下的数最小,就应该先去消大的,所以从最大的开始依次消即可。你看,我们生成方案也有了。

接下来,凭什么答案不能更小?很显然,我们不能剩下两个 1 来得到 1,所以不存在更小的答案。

CF1025C Plasticine zebra

思维题还有一个特点,就是要打破你的固有认知,跳出你的套路,去打开你的想法。

提醒:此题难度虚低。

手玩样例其实什么也解决不了,看到区间翻转就想用平衡树?但是你觉得你用的平衡树能维护一些什么呢?他什么也做不了,只能眼睁睁看着你被样例蹂躏。

现在,玩样例没招了,自己再造几个试试也没招了,我们该怎么办?直接开始分析?可是你别忘了,这样子你又变回了我们开头说的那样,看着题干干着急。

我们是把一个字符串分成两段,然后两段分别翻转的。是的,整个字符串全进行了操作。而翻转有什么特点?给你一个手环,它的珠子排列顺序是红黑绿,你把它翻过来看,它的红色难道能跑到黑绿中间吗?肯定不能。那为什么会这样?因为它是环。

所以,我们考虑把这个字符串首尾相连成一个环,再去玩样例,你发现翻转后对你的手环没有任何影响。

现在,题目便成了求环上的最长交错字段,扫一遍就完事儿了。

我们在三个基础一些的题目上念叨了很久,我们的目标是让自己的思路清晰,而不是解题。掌握好这个节奏,我们来看一道数学高考题。

2026 新高考一卷 T14

设实数 q 满足:存在数列 \{a_n\},使得对于任意 n \in \mathbf{N}^*,均有

a_1 + a_2 + \cdots + a_{3n} = n^2 + n

\{a_n\} 中有某连续9项 a_k, a_{k+1}, \cdots, a_{k+8} 是公比为 q 的等比数列,则 q 的最大值为__

我们先来做一个所有高中生拿到这个题目都会做的第一步:把原题干下标调整为 n-1,然后两个等式相减。我们可以很轻松的得到 a_1+a_2+a_3=2a_4+a_5+a_6=4a_7+a_8+a_9=6 依次类推。

到这里,很多考生就戛然而止,不知道下一步该怎么做。我们发现我们能得到的全是连续和,片段和,无法定位到具体的一个 a_i 上。

等等,片段和?

考虑为了让 q 最大,我们很显然考虑要用前面的数,因为后面的片段和越来越紧密,会导致 q 更加趋近于 1

问题是,如果对前九个数使用片段和,2,4,6 不是等比数列。我们又该怎么办?

很简单,把第一位扔掉,把第十位引入进来。这样第一个片段就被打断了。我们考虑对下标 4-6 与下标 7-9 使用片段和性质,得到 \sqrt[3]{\frac{3}{2}}

这个答案为什么符合标准?因为第二和第三位,以及第十位可以随便给,我们一定存在一组合法的构造方案。

P17130 [ICPC 2025 Shanghai R] Yet another mailbox problem

拿到这道题,先看看样例。样例 1 给了八条路径的长度,前三个都是 1,说明长度为 1 的路径有三条,而且权重都是 1。第四条是 2,对应路径 (e_5,e_1) 长度为2。到这里我们大概明白了这个题在问什么。

如果我们用一个优先队列,每次弹出字典序最小的路径,然后把它的所有后继边扩展出来的新路径都放进去,这样做看起来是正确的。但仔细想想,每条路径都要存一个权重序列,扩展的时候还要复制这个序列,k5e5 量级,路径长度可能很长,空间和时间超了。这个思路走到这里就卡住了。

这时候我们回过头来看题目给了什么特殊的条件。边权只有 18,这个数字很小,小到我们可以按权重来分层处理。既然字典序比较是先比第一个权重,再比第二个权重,那如果我们把所有权重为1的边先处理完,再处理权重为 2 的边,依次类推,不就天然符合字典序的要求了吗?

我们再仔细看样例的那八条路径。路径 (e_5,e_1)(e_5,e_1,e_4) 有一个共同点,它们都经过了顶点 2,然后从顶点 2 继续往后走。也就是说,所有到达同一个顶点的路径,它们接下来的选择是完全一样的。那如果我们把"所有当前路径的终点"放在一起处理,一个顶点的出边只需要遍历一次,而不需要每条路径都遍历一次。

所以,我们直接 dfs 按照权重枚举,对于当前集合里的每个终点,找出所有这个权重的出边,每找到一条就输出一条路径,并把新的终点收集起来。一层一层走即可。

至此,问题解决。

我们来思考一下我们是怎么得到这个做题方案的,从错误的思路引入到正确的思路,质疑一开始的做法,并思考如何解决该漏洞。

[AGC023F] 01 on Tree

我们拿到这道题,先不考虑树的结构,想一个更简单的问题:如果给你若干个 01 串,你可以任意安排它们的顺序,怎么安排能让逆序对最少?

考虑相邻的两个串 ab,如果 a 排在 b 前面,贡献的逆序对是 a1 的个数乘 b0 的个数。反过来如果 b 排在 a 前面,贡献是 b1 的个数乘 a0 的个数。我们比较一下这两种排列哪个更好:

a$ 在 $b$ 前面:$cnt(a,1) × cnt(b,0) b$ 在 $a$ 前面:$cnt(b,1) × cnt(a,0)

如果 ab 前面更优,那么:

cnt(a,1) × cnt(b,0) < cnt(b,1) × cnt(a,0)

化简一下:

\frac{cnt(a,1)}{cnt(a,0)} < \frac{cnt(b,1)}{cnt(b,0)}

所以比值小的应该放在前面。

回到原题,树上的限制是每个节点的祖先必须排在它前面。我们观察到一个性质:如果一个节点的权值是 0,那么一旦它的父亲被选完,就应该立刻选它。因为 0 放在前面不会产生新的逆序对,而且它还能帮后面的 1 挡住一些逆序对,所以越早选越好。

基于这个观察,我们可以把每个节点看作一个块,块里记录两个信息:0 的个数和 1 的个数。一开始每个节点自己是一个块。然后我们按照比值

\frac{cnt(1)}{cnt(0)}

从小到大的顺序,每次找到比值最小的块,把它和它的父亲块合并。

合并的时候,新块内部的逆序对会增加,增加的量就是父亲块里 1 的个数乘子块里 0 的个数,这个要累加到答案里。然后把两个块合并成一个新块,继续找下一个比值最小的。

这个过程可以用并查集加优先队列来实现。每个块维护它的根节点、0 的个数、1 的个数,以及它当前所属的块的根。每次从堆里弹出比值最小的块,如果它已经被合并过了就跳过,否则找到它的父亲所属的块,合并,更新信息,再把新块放回堆里。一直合并到只剩一个块为止,答案就是过程中累加的所有逆序对数。

尾言

在退役后回归文化课的时候,总感觉学数学力不从心,凭什么别人能一下就想到,我想不到?

后来发现是自己思维习惯的问题,跳跃性思维是需要连续性思维的积累的,而这篇文章便是《让思维顺利成章:初尝试后的理论分析》的思考过程。希望对各位有所帮助。