阅读程序 · 答案 ABC · 考点:字符串哈希、树形结构、二叉树基础、质数与合数、分治算法
← 整套速查表 CSP-S 提高级 全部真题#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000000 + 5;
const int P1 = 998244353, P2 = 1000000007;
const int B1 = 2, B2 = 31;
const int K1 = 0, K2 = 13;
typedef long long ll;
int n;
bool p[maxn];
int p1[maxn], p2[maxn];
struct H {
int h1, h2, l;
H(bool b = false) {
h1 = b + K1;
h2 = b + K2;
l = 1;
}
H operator + (const H & h) const {
H hh;
hh.l = l + h.l;
hh.h1 = (1ll * h1 * p1[h.l] + h.h1) % P1;
hh.h2 = (1ll * h2 * p2[h.l] + h.h2) % P2;
return hh;
}
bool operator == (const H & h) const {
return l == h.l && h1 == h.h1 && h2 == h.h2;
}
bool operator < (const H & h) const {
if (l != h.l) return l < h.l;
else if (h1 != h.h1) return h1 < h.h1;
else return h2 < h.h2;
}
} h[maxn];
voi
(本题为阅读程序 / 完善程序,完整题目与测试数据见平台)这题核心是把筛质数、双哈希构建和二叉树合并揉在一起考。拿到题先看 init 里 p1[p2] 是干嘛的(底数幂),再看 solve 里 h[i] 怎么拼(左根右),最后排序去重。关键就是识别出合并顺序对应中序遍历,以及时间复杂度瓶颈在排序而非筛法。
最容易混淆的是 h[i] 的拼接顺序,很多人看到先算左子树再算右子树就以为是后序,其实代码里 h[i] = h[2*i] + h[i] + h[2*i+1] 明显是左→根→右,对应中序。另外时间瓶颈也常被误判为筛法,其实筛法 O(n log log n) 远小于排序 O(n log n),别被 init 里的两层循环唬住。还有双哈希的 K1/K2 是偏移量,改它确实会撞出不同结果,这点要留意。
这是一道综合题,把埃氏筛法、双哈希和二叉树合并串成一个程序。核心考点是读懂代码里 h[i] 的拼接逻辑,识别出它对应二叉树的中序遍历,并判断时间复杂度的瓶颈在哪里。
1. 合并顺序的陷阱:代码里 h[i] = h[2*i] + h[i] + h[2*i+1] 是左→根→右,对应中序遍历。很多同学看到先处理左子树就以为后序,或者看到最后处理右子树就以为是后序,这里就是故意让你区分清楚。 2. 时间瓶颈的误导:init 函数里有两件事:筛质数 O(n log log n) 和预计算底数幂 O(n)。但真正拖慢程序的是 solve 里的排序 O(n log n)。命题人把筛法和排序放在同一个函数里,让你别被两层循环吓住。 3. 常数偏移的隐蔽影响:K1、K2 只是给根节点加个偏移,看似无关紧要,但改它们确实会改变哈希值,进而影响排序去重的结果,这是个小细节坑。
第一步:看 init
p1[i] = B1^i mod P1,p2[i] = B2^i mod P2,这是哈希底数的幂次表。p[0]=p[1]=false,外层 i 从 1 到 n,内层 j 从 2*i 开始。复杂度 O(n log log n)。第二步:看 H 结构
h1 = b + K1,h2 = b + K2,l = 1。b 是 p[i](质数标记)。所以质数根节点哈希是 (K1, K2, 1),非质数是 (0,0,1)。operator +:新长度 l = l + h.l,新 h1 = (h1 * p1[l] + h.h1) % P1,同理 h2。这就是标准的字符串哈希拼接。第三步:看 solve 的合并顺序
h[i] = h[2*i] + h[i] + h[2*i+1]。h[i] = h[2*i] + h[i]。第四步:输出与去重
h[1].h1(根哈希的第一模)。h,再用 unique 去重,返回不同哈希值的个数。排序是 O(n log n),去重 O(n)。判断题 1:假设 maxn 改为 n+1,算法时间复杂度是 O(n log n)?
判断题 2:时间瓶颈是 init 函数?
判断题 3:改 B1 或 K1 会输出不同结果?
选择题 4:输入 10,第一行输出?
选择题 5:输入 16,第二行输出?
h[left] + h[root] + h[right] 是左→根→右,不是后序的左→右→根。选择题 1 选 C 中序,不是 D 后序。从数据看,二叉树基础题在 2024-2026 年爆发式增长(2024 年 60 题、2025 年 67 题),树形结构题也逐年上升(2026 年 8 题)。字符串哈希和分治算法近年考得少,但 2024 年各有一题。结合趋势,未来 CSP 提高级很可能会继续考“树形哈希 + 排序去重”的组合,甚至可能把哈希换成其他同构判断(如树直径、重心等)。暂无足够依据预测具体年份和题号。