非传统题与随机算法

非传统题与随机算法

1 通信题

1.1 单轮通信题

这类通信题一般指,仅进行一次通信的通信题,这也是大多数通信题的形式。

一种通信策略是对信息的(有损)压缩,你可以在保证一定正确率的情况下只传递部分信息。

另一种策略是将信息转化成另一种形式,比如哈希。

在实际问题中,需要关注对信息的需求,分析哪些信息是冗余的,这往往是解决通信题的关键。

例题 1.1.1:Multiple Communications

https://qoj.ac/contest/997/problem/4675

题意:

给定两个长度为 100 的序列 a,b,序列中的每个元素是 1000 位的二进制数。A 只能看到 a,他只能向 C 发送 3000 个二进制位,类似的,B 只能看到 b,他也只能向 C 发送 3000 个二进制位。

C 要根据收到的信息回答 100 个问题,每个问题给定一个二进制数 c,他需要回答正整数 x,y 满足 ax xor by=c,回答对 96 个问题即算 AC。

解法:

1001000 位二进制数,总信息量为 100000 bits,但是我们只能发送 3000 bits

考虑一下有损压缩,我们从 1000 位中随机选择 30 位,每个数只保留这些数位后传递。

看起来这样很可行,实际上如果这 100 个数中,前 992 个数位都是相同的,只有后 8 位不同,正确率会大大降低。

再考虑一下哈希,一个二进制数可以看成一个集合,异或运算可以看成集合的对称差运算,而对集合的哈希可以考虑 xor-hashing,即,对每一个数 x 随机一个 [0,2301] 的权值 w(x),一个集合 S 的哈希值 H(S) 定义为 xorxS w(x)。可以直观的感受到,任取一个集合,它的哈希值可以近似看做 [0,2301] 里的一个随机数。

由于异或存在消去律,令两个集合 S,T 的对称差为 ST,则有 H(ST)=H(S) xor H(T)

回到题目中,我们将题目里的所有二进制数看成集合,异或看成对称差运算,A 和 B 共用同一个 w (比如使用相同种子的 mt19937 依次生成 w(1),w(2),,w(1000),或者本地生成好后打表),对每个集合计算哈希值即可。

例题 1.1.2:Mapa

https://qoj.ac/contest/1271/problem/6669

题意:

A 有 N 个正整数二元组,第 i 个二元组为 (xi,yi),保证 xi 互不相同,A 要发送 K 个二进制位给 B。

B 在收到信息后,需要回答 Q 个问题,每个问题给定一个 x0,B 需要回答一个正整数 y0 使得存在一个二元组 (x0,y0),保证一定有解,即 x0x1,x2,,xN 中出现过。

1N,Q100, 1xi,yi109K3000 即可通过。

解法:

直觉上特别违背信息论,因为只能传递 3000 bits,而传递 yi 已经需要 3000 bits。

由于 B 在回答问题的时候知道了 x0,我们不妨思考一下是否有必要传递 xi

先考虑有损压缩,尝试随机删掉所有 xi 的某一个二进制位,只要不出现两个相同的 xi,就可以一直删,删完之后只需要额外传递 30 bits 表示哪些位被删掉了,此做法可以得到 58 分左右。

但是我们的目标是满分,我们不能在 x 上花费任何的代价。

假设 B 知道了所有 xi,那么 A 只需要按 xi 排序后传递 yi。思考一下能否将给定的二元组转化成一些固定的 xi,比如将所有 xi 变成 [1,N] 的排列。

拉格朗日插值!

N 个二元组唯一确定了一个 N1 次多项式,将这个多项式求出来,传递 [1,N] 的点值(传系数也行),插值一下就能求出 y0,由于插值有除法,可以在模 109+7 下算,需要的位数不变。

例题 1.1.3:Ancient Machine

https://qoj.ac/contest/878/problem/3098

题意:

给定一个长度为 N 的,只包含 X,Y,Z 的字符串,你可以不断的删去一个字符,如果选择了一个 Y,且它左边是 X,右边是 Z,你会得 1 分,其它情况不得分。构造一个删除的方案,最大化得分。

A 和 B 都知道 N,但 A 知道字符串,B 不知道。A 可以向 B 发送 L 个 bits,B 在收到信息之后,需要构造出方案。

3N105, L 不超过 70000 即为满分。

解法:

按照这节的引言所说,首先我们需要明确 B 需要什么,不妨简化一下问题,如果 B 知道了所有信息怎么做。

将最左边的 X 和最右边的 Z 拿出来,只有中间那一段有用。对于一个同字符的极长连续段,其中也只有一个有用。也就是说字符串一定可以被转化成 XY?Y?Y?...?YZ 的形式。观察到其中一定存在子串 XYZ,将这个 Y 删去,然后删去两边之一(注意不要把头尾删去),就能得到一个子问题。

一个特别简洁的方法是,取最左边的 Z,然后从这个 Z 前面的位置不断往前删,直到前面只剩下一个开头 X(注意这个 X 不要删掉),然后删去这个 Z,取下一个 Z 进行相同的步骤。这个做法只需要知道所有 Z 的位置。进一步观察,发现只需要知道每一个 Z 的连续段的最后一个位置就行。

也就是说,我们发送的长度为 N01 串不存在相邻的 1,考虑计算一共有多少长度为 N 的串,写出 dp 式子发现就是斐波那契数列的第 N 项,小于 270000,理论可行,但是数字太大了,算起来很慢,退而求其次,考虑分块,枚举一些块长,发现:

将串每 63 个分一块,用 44 bits 传递就行。

至于如何实现?我们可以计算出一个串是字典序第 rank 小的串,传递 rank,解密的时候,类似线段树二分,可以根据 rank 是否小于等于填 0 后的方案数,确定每一位是 0 还是 1

习题 1.1:

1.2 实时通信题

1.1 相对,这类通信题中,各方可以进行在运算过程中实时通信。

大多数情况下,一方充当“交互库”的角色,解决问题的关键是如何设计另一方的问题,即,我们首先需要明确另一方需要什么,然后问题就转化成了 1.1 的形式,我们需要尽可能高效的回答另一方的问题。

下面这个例题中,双方互相充当对方的“交互库”。

例题 1.2.1:Two Transportations

https://qoj.ac/problem/67

题意:

A 手上有一张 N 个点 MA 条边的无向带权图 GA,B 手上有一张 N 个点 MB 条边的无向带权图 GB

A 想知道,若考虑所有 MA+MB 条边,即把两张图“并起来”后,节点 0 到每个点的最短路。A 和 B 可以实时通信。

1N2000, 0MA,MB5×105,1500,总发送量不得超过 58000 bits。

解法:

考虑 Dijkstra 的过程,每次找到一个距离最小的点去松弛,如何知道最小的点?我们可以令 A 和 B 把最小的距离发给对面,如果发现自己的距离小,就将对应点的编号发给对面,这样双方都知道最小的点了。

还有一个问题是,这个距离可能会达到 O(NW) 级别,W 是边权范围。令 M 为目前已知点中距离的最大值,那么距离一定在 [M,M+W] 之间,传递的时候减去 M 再发送,一轮松弛传递的比特数量为 2logW+logn=29,总共不超过 29n=58000 比特,可以通过。

习题 1.2:

1.3 加密通信

有些题目交互库是自适应的,也就是说 A 和 B 的通信,会被很“聪明”的交互库干扰,一般来说这个交互库真的很聪明,以至于在假设交互库的策略均匀随机的情况下,即使有着极高的正确率,依然无法通过。

但是,你不让交互库看出来你在说什么,不就行了吗?😂

例题 1.3.1:Magic Show 

https://qoj.ac/contest/1684/problem/8726

题意:

A 和 B 参与一个游戏,他们被关在两个房间中,不能相互通信,游戏的步骤如下:

  • A 选择一个整数 n[2,5000] 告诉主持人 C。
  • C 告诉 A 一个整数 X[1,1018]
  • A 生成一个 n 个节点的有标号的无向无根树,告诉 C。
  • C 从树中删去至多 (n2)/2 条边,并将剩余的边告诉 B。
  • B 根据这棵残缺的数猜出 X

解法:

我们不妨传递一条链,A 和 B 事先商量好一个随机排列 P,A 将所有节点 u 变为 P(u) 后传递,B 接收到信息后将所有节点 u 变为 P1(u) 后,即得到原来的链。

在 C 的视角中,他收到的信息可以近似的看成一个随机排列,他不知道在说什么,只能闭眼乱删一半的边。

n=4800,其中令 [1,1200] 为 I 类点,[1201,2400] 为 II 类点,[2401,4800] 为 III 类点。对于 X 的每一个二进制位,分配 20 个 I 类点(即传递 20 次,因为 C 的策略已经退化成随机删边,一个 bit 的正确率为 1220,已经足够大),如果这一位是 0,我们不管它,如果这一位是 1,我们将每一个 I 类点连上一个 II 类点,最后用所有 III 类点把它们串起来。

B 接收到信息之后,只需要看每一个二进制位,是否存在至少一个 II 类点相邻,即可确定这一位是什么。

这题还有很多离谱做法,比如把节点 i 连到 (xmod(i1))+1,直观上你不可能从 5000 个数中选出 2500 个数使得它们的 lcm1018

或者,对于所有点,如果代表的数位是 0,就挂在 1 上,如果代表的是 1,就挂在 2 上,但这样交互库可以把挂在某个点上的所有边都删掉。那我们就事先商量好一个随机 01 串,把每个点的策略异或一下,在交互库的视角里面,它只知道一个随机 01 串,如果 X 的每个二进制位用 80 个节点代表,正确率高达 (1280)60 约为 0.99999999999999999999995036916325,非常优秀。

😅。

习题 1.3:

2 交互题

一般来说做交互题时,你需要先明确解决问题需要什么信息,针对这一点设计询问方式。

一些题目需要运用启发式算法(俗称乱搞),还有一些题目需要发现一些性质,或者“灵光一现”。

2.1 随机化与启发式算法

这部分的题目,解法大多为随机化算法或启发式算法。

对于复杂的随机化算法或启发式算法,只需要感性理解复杂度,不需要证明,多数情况下,不断加入你所认为正确的优化,优化着优化着,就过了。

例题 2.1.1:网络恢复

题意:

https://uoj.ac/problem/550

给定整数 NM,有一张 N 个点 M 条边的无向简单图,需要你猜测出所有的边。

你可以进行至多 50 次如下操作,每次操作步骤如下:

  1. 给每个节点 i 设定一个权值 ai[0,2641]
  2. 选取一个边的子集 S
  3. 对于每个 i,交互库会计算出 bi=xoru=1n[(i,u)S]au,即,在只考虑 S 中的边的情况下,所有 i 的邻居的权值异或和。
  4. 你会得知所有的 bi

N=104,M=3×105,不自适应。

解法:

将所有边随机分成大小相等的 50 份,对每一份进行一次询问,ai 随机生成,得到的 bi 可以看做是对 i 的邻居集合进行 XOR-Hashing 的结果。

如果是一棵树的话,可以类似拓扑排序,逐步删叶子(叶子的判定只需要检查 bi 是否为某个设定的权值即可)。这个想法可以拓展到图上,先逐步删度数为 1 的点,如果没有了,就随便取一个点 x,有很大概率其度数为 2,枚举一个点 y,用哈希表查询是否存在另一个点 z,如果有,就成功删掉了 x,此时它的两个邻居 y,z 可能成为度数为 1 的点,加入队列后继续删即可。

例题 2.1.2:Longest Trip

https://qoj.ac/problem/7119

题意:

给定一个 N 个点的无向图,保证对于任意三个不同的节点 u,v,w,边 (u,v),(v,w),(u,w) 中至少存在一条。

你可以进行若干次询问,每次询问给出两个点集的子集 A,B 满足其交集为空。交互库会告诉你是否存在 x,y 满足:xA,yB ,且边 (x,y) 存在。

试通过询问求出一条最长路。

3N256,询问不超过 400 次得满分,不自适应。

解法:

考虑充分利用“每三个点之间至少有一条边”的性质。

维护两条链 L1,L2,令两条链的第一个节点为 s1,s2,最后一个节点为 t1,t2,步骤如下:

  • 检查 t1,t2 之间是否有边,如果有就将 L2 接在 L1 后面,然后清空 L2
  • 任取一点 u,检查 u,t1 之间是否有边 ,如果有就将 u 加入 L1 末尾。如果没有,此时要么 L2 为空,可以把 u 加到 L2 的末尾;要么 u,t1 没边,t1,t2 没边,u,t2 一定有边,也可以把 u 加到 L2 的末尾。

执行上述步骤,会得到两条链,查询 (s1,s2),(s1,t2),(t1,s2),(t1,t2) 是否有边,如果其中之一有,找到哈密顿路,做完了。否则由于 (s1,s2),(t1,s2) 没边,(s1,t1) 有边;由于 (s2,s1),(t2,s1) 没边,(s2,t2) 有边,也就是我们会得到两个环。然后查一下两个环之间是否有边,如果没有,输出最大的环;如果有,二分找一下,然后在一个环绕一圈,经过这条边走到另一个环,然后再另一个环上在绕一圈,找到哈密顿路。

询问次数是 O(n)+2logn 的,得到 85 分,考虑给 O(n) 部分稍微改改。

维护两条链,可以设计势能函数为:两条链大小之和。检查 t1,t2 是否联通这一步并不会减少势能。

如果同时维护多条链,每次随机取两条链,检查末尾是否有边,可以设计势能函数为:链的个数。检查末尾是否有边这一操作,有概率减少势能。

还有一个优化是,有时会已知存在两条链的末尾之间没有边,此时不需要检查,直接拿来做即可。

例题 2.1.3:麻将

https://yundouxueyuan.com/p/YDRG005F?tid=65ccf4cbfbfb0fad8af18874

题意:

本题的麻将不含字牌,共 3×4×9=108 张,不允许七对子胡。

在本题中,你需要和交互库玩如下游戏:

  1. 游戏开始时,交互库将这一副麻将按某种顺序排列组成牌堆,保证牌堆顶 13 张牌的听牌集合大小 2
  2. 交互库将牌堆顶 13 张牌作为她的手牌,然后将牌堆顶第 14 张到第 43 张牌(共 30 张牌)亮出,你可以看到这些牌,注意这些牌可能属于交互库手牌的听牌集合,也可能不属于。然后移除这 43 张牌(即此时牌堆顶的牌,是初始牌堆的牌堆顶第 44 张牌)。
  3. 你猜测一张牌,若这张牌属于交互库手牌的听牌集合,则游戏结束;否则交互库会亮出牌堆顶的 3 张牌中不属于听牌集合的所有牌,并移除牌堆顶的 3 张牌,你需要继续猜测。注意,如果听牌集合内的一张牌全部被翻出,其仍然属于听牌集合
  4. 游戏结束时,令你的代价为你的猜测次数。

你需要尽可能最小化游戏的代价。

保证数据随机,10000 局游戏猜测次数不超过 41301 次即可通过,更多细节见原题面。

解法:

这是一道考察纯启发式算法的交互题。

如果从 5 往两边猜,并跳过已经确定不合法的,可以得到 12 分上下。

本题中保证至少两面听,大致可分为如下几种听牌的类型:

  • x,x+1 型,例如 1m 1m 1m 2m 2m 2m 3m 3m 3m 4m 4m 2s 3s
  • x,x+1,x+2,x+3 型,例如 1m 1m 1m 2m 2m 2m 3m 3m 3m 1s 2s 3s 4s
  • “双碰”型,例如 1m 1m 1m 2m 2m 2m 3m 3m 3m 4s 4s 5s 5s

也可能会有 3 面听,事实上这种情况出现的较少,对代价的贡献也比较小,我们可以忽略。

介绍一下麻将的防守技巧:

  • 筋牌:假设你知道对面不听某花色的 4,那么听 1 的概率会大大降低(不存在 2,31,2,3,4 型),听 7 的概率会有所降低。
  • 壁牌:假设牌河中已经有很多某花色的 3,那么听 1,2 的概率会大大降低;若牌河中有很多 4,6,那么听 5 的概率会大大降低。

上述技巧不能适用于“双碰”型,即 3 个面子 2 个雀头的听牌形状。事实上这类听牌在现实生活中,在不知道对方是这类听牌的情况下也没有很好的防守技巧。

我们需要对筋和壁设计估价函数,如果对这两种防守技巧设定参数,会变得很复杂,尤其是壁牌。但这两种技巧有一个共性,即它们都减少了在剩余牌中凑出听牌形状的方案数。

我们令 f(x) 表示牌 x 的估价函数,对于 x,x+1 型是很好设计的,把没有筋牌的部分两张牌的剩余数量乘起来就行;对于 x,x+1,x+2,x+3 型,由于要乘四张牌,显然不平衡,根据物理学中的单位统一,把这四张牌乘起来开根;“双碰型”的话,它还是需要乘四张牌后开根,而且这种类型比较特殊,它的出现概率会随着你猜测次数增大而增大,所以还需要乘上一个随操作次数递增的函数,可能要调一会儿这个参数。

这个函数的表现并不是很理想,我们令 g(x) 表示,若钦定 x 不合法后,所有牌的 f(x) 之和,然后按选取 g(x) 最小的即可。

欢迎各路大神薄纱 std!

习题 2.1

2.2 交互题中的思维题

这一节中的题目,往往需要多发现性质,或者需要“灵光一现”。

例题 2.2.1:Ancient Machine 2

https://qoj.ac/contest/1300/problem/6774

题意:

你需要猜测一个长度为 N=100001S,一次询问需要给出一个整数 m[1,1002] 和两个长为 m 的序列 a,b,序列中的每个元素 [0,m1]

交互库会做如下的过程,初始时令 u:=0,然后进行 N 次操作,第 i 次操作为:若 Si=0,则令 u:=au;若 Si=1,则令 u:=bu,其中 := 表示赋值操作。

操作完后会告诉你 u 的值。

也就是说,你需要给出一个大小为 m 的自动机,交互库会返回跑完这个字符串 Su 的值。

你至多进行 1000 次询问,欲获得满分,你需要保证 m102

解法:

n=1000,即答案长度。

由于不需要优化询问次数,且询问次数限制为 n,考虑问出 n 个方程把答案解出来。

一个想法是选一些位置,问出它们的异或和。询问的自动机大概是有左右两部分,读取到这些位置的时候,如果这个位置为 1,就跳到另一部分,最后根据落在哪个部分得到某些位置 1 的个数奇偶性,也就是这些位置的异或和。

搞两个长度为 x 的环,对于每个环上的第 y 个节点,1 边指向另一个环的下一个节点,其余边均指向当前环的下一个节点,询问这个自动机,可以得到所有模 xy 的位置上的异或和,只需要选 n 个二元组 (x,y) 就行。

不幸的是,这个矩阵不满秩,如果想要满秩的话,x 的最大值能达到 54,即 M=108,不能通过。

考虑先确定前 100 位,这个是简单的,确定第 i 位时,节点 j(j<i) 两条边指向 j+1,节点 i0 边指向 i+11 边指向 i+2i+1,i+2 的两条边均指向自己。

然后考虑确定后 100 位,确定倒数第 i 位时,询问 0+(i1) 的 KMP 自动机,看是否在最后一位上匹配。如果匹配则第 i 位是 0,否则是 1

对于中间 800 位解方程,正好就卡进去了。

用 bitset 做消元,时间复杂度 O(n3/w)

习题 2.2

3 提交答案题

常用的方法有:iddfs,A*,idA*,模拟退火,爬山,随机调整,估价函数。

但这不意味着只要了解了这些算法,你就是提答高手了。对什么设计 A* 的估价函数,怎样剪枝,对什么退火,如何随机,怎样实现更高效,都是要慢慢摸索的。

3.1 搜索类提答

此类题目的关键是找一个好的估价函数。

好的估价函数往往需要一定的时间尝试,“提答花的时间越久分数越多”这句话的原因就在此。

例题 3.1.1:N2 数码游戏

https://qoj.ac/problem/6689

题意:

用尽可能少的步数求解数字华容道。

题解:

对于测试点 1,可以爆搜,复杂度 O((N2)!poly(N))

对于测试点 2,6可以剪十六个小纸片玩,观察发现前若干次操作一定是转矩形的最外面一圈,类似于 UUULLLDDDRRRUUULLLDDDRRR... 的过程,当把 1,2,3,4 转到最上面的时候,剩余部分可以暴力或者用下文方法解。

考虑 A*,设计一个估价函数,每一层只保留一些可能比较优的状态,可以试试如下几个。

  • 每个数到终点的曼哈顿距离,的和/平方和/立方和/平方根和。
  • 重新定义距离:(x1,y1),(x2,y2) 的距离为 (|x2x1|+1)(|y2y1|+1),算和/平方和/立方和/平方根和。
  • 将距离乘上 0 到这个数的距离,算和/平方和/立方和/平方根和。

实测和/平方根和比较优秀。

这样子会出现一个现象,目前队列中估价函数最低的会在两个数中反复横跳,每次扰动一步显然是不够的。可以在模 2/3/4=0 的某一轮中删减状态。

需要调一调删除的频率和保留的状态数。

当然估价函数并不全面,比如有两个相邻但位置相反的数,空格又隔得特别远。其实这种状态是很劣的,但这几种估价都会认为这种状态很优秀。或者说多个路径交错在一起,也是特别劣的,但很难设计函数把它们区分开,欢迎各位来交流更好的估价函数。

题外话:关于多项式复杂度的构造方法,也是我的赛时做法:

  • 大概思路是按照 1,2,,N2 的顺序归位,已经归位的不去动它。
  • 对于前 N2 行的前 N2 列,记录状态 (ux,uy,ex,ey),表示目前需要归位的数和空格分别在什么位置,爆搜就行。
  • 对于前 N2 行每一行的最后两列,并不能保证上一条能跑出解,但是我们一定可以把棋盘变成下面的形状之一(. 表示空格,? 表示没被归位的数字):
1 2 . 3
? ? ? 4
1 2 4 .
? ? 3 ?

所以记录状态时记录两个数的位置和空格的位置,也一定能得到解。

  • 对于后两行,由于最后一行极有可能顺序不对,上述方法不能使用。从左往右枚举列,同时归位这一列的两个数,假设 N=4,目前归位 9,13,只需要在第三行令 139 挨在一起,然后转下来就行,也可以记录三个坐标爆搜。
1 2 3 4
5 6 7 8
? 13 9 ?
? ? ? .

复杂度 O(n7)。肯定有更优的做法。

但这样构造,我只在测试点 9 得到了 3 分,其余均为 2 分。

习题 3.1

3.2 随机类提答

3.1 同理,需要尝试退火的对象,尝试不同的参数。

要注意的是,一般来说,跑一轮退火容易陷入局部最优解,跑多轮退火就能解决这一点。

例题 3.2.1:Road Service

https://qoj.ac/problem/118

题意:

给一棵无向无权树,你需要往里面加入 K 条边,尽可能最小化:两两节点之间的最短路长度之和。

解法:

说一下我做这个题的过程:

我一开始想的是,加入一条令总距离减少最多的边,但这样实在是太慢了,于是我就随了几条边取最优,这个表现并不是很优秀,在 case 2 只得到了 18% 的分数。

打算给 case 1 写一个暴力,算量是 (n(n1)/2k)n2,在一个不错的电脑上能 10 分钟内出解,发现连出来的是一个菊花图,想了想发现菊花图确实很对,因为菊花图内部的路径非常短,每个点到菊花图上的路径长度也很小。

直觉告诉我,菊花的根选择重心,但是选择菊花叶子比较麻烦,因为算一次代价是 O(n2) 的,但是可以随机尝试几个叶子啊,这样能在几分钟内在 case 2 跑出 60%70%,调用全家电脑去跑枚举所有叶子的程序,得到了所有点的 80%90%

题目中的代价不好维护,我想了一个估价函数,我们不妨忽略菊花,直接把菊花中的所有点“缩起来”。由此想到估价函数:每个点到菊花根的最短路径之和,这样计算一次代价只需要 O(n) 的时间。

先贪心选令估价函数减少最多的点,选出一个集合,枚举集合内哪个作为根,可以在 O(kn2) 的时间内运行完毕,而且非常优秀,能在所有点得到 90%95%

对叶子退火试试?每次扰动选择一个叶子和菊花图外的点交换并估价,每个点跑五六分钟就可以得到满分。

此题还有别的做法,一种是对叶子爬山,每次扰动随机一个子集换出,这个子集大小需要调一调,你甚至可以动态调整,发现爬不动了就多换一点。

还有一种是最小化估价函数的确定性做法,类似 NOI2008 奥运物流的二维树上背包,实现的好可以在一秒内出解,很厉害。

我的退火代码在 i7-1260P 2.10GHz 16GB 上,能在一分钟的时间对 case 6 处理完毕。

习题 3.2

碎碎念

熟悉笔者的都知道,笔者是非传统题和启发式算法的究极爱好者,热衷于用各种“歪解”过题。

比如 2023 NOIP t3 ,我在长时间的坐牢之后,突发奇想用特殊性质的代码去跑没有特殊性质的大样例,发现只筛掉了约一半的测试点,由此尝试把序列 reverse 一下再跑一遍,就通过了;在 2024 联合省选 d2t2 中,对贝尔数的搜索加了很多剪枝,多跑过了 15 分。

到了 NOI 2024,我非常幸运的在 day1 遇到两道擅长的题目:t1 是本文开头提到的 xor-hashing,t2 是我擅长的交互题,这两道题都是飞速通过,给 t3 留下了充足的时间;在 d2t1 中,根据多年写搜索的经验,想到去优化搜索的最后一层递归,多获得了 10 分,这让我即便在误判 d2t2 难度,丢掉 40 分的情况下,凭借这 d2t1 多的 10 分和 day1 的优势,擦线进入了集训队。

进队之后,我被邀请到一些学校讲课交流,在正式内容提前讲完的情况下,我都会用之前做的非传统题填满剩下的时间。如果一切顺利,这篇文章会是我的候选队论文,可惜我在 CTT 中惨烈坠机,准确的说,根本就没起飞,没有任何一场比赛进入过前 30

每当有人和我提起“乱搞无用论”之时,我都会用我的 oi 生涯坚定的反驳他,如果我不会乱搞,这个集训队我还能进吗,甚至说,这个江苏省队我还能进吗?

希望你们都爱上乱搞,爱上非传统题!

posted @   znstz  阅读(245)  评论(5编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示