八级编程模板 · 最后冲刺默写清单

15 个默写模板按 图论 / 组合 / 倍增 / 树形 DP 四大类组织,覆盖八级编程题主要高频型。目标不是"看懂",而是合上清单、限时默写到能 AC。每个模板可一键盖住骨架自测。

怎么用这张清单

用法:每个模板 ①先盖住骨架自己默写 → ②点开对照检查 → ③做自测题限时 AC → ④回看易错点。所有骨架均为 C++14,已编译跑过样例。

考场通用开头
C++14

大数组开全局;涉及计数 / 距离和一律 long long + 随时取模。

一、图论(点骨架可盖住 / 揭开)

1

Floyd 全源最短路

最短路
触发信号:点很少(n≤300/500)、要任意两点最短路、或多次问不同点对。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. k 一定在最外层,写到里面就错。
  2. 不连通用 INF,松弛前判 d[i][k]<INF && d[k][j]<INF 防溢出。
  3. 重边初始化取 min。Floyd 可处理负权边(但不能有负权环)。
变体·传递闭包:把 min(+) 换成 or/andf[i][j] |= f[i][k] && f[k][j];
限时自测:B3647 模板 Floyd → 进阶 P2419 传递闭包 / P15805 增量 Floyd
2

Dijkstra 堆优化(单源,正权)

最短路
触发信号:单个起点、边权非负、n/m 较大(10⁵)。八级只考 Dijkstra,别用 SPFA;单源负权才需 Bellman-Ford。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 小根堆:priority_queue<pli, vector<pli>, greater<pli> >(注意两个 > 之间空格)。
  2. distlong longif(dd>dist[u])continue; 不能漏。
  3. 无向图边要加两遍。不要用 C++17 的 auto [d,u],旧评测会报错。
限时自测P10726(八级真题,最短路/DAG-DP);模板题 P4779 标准版
3

Kruskal 最小生成树(并查集)

MST · 稀疏图
触发信号:无向带权图、连通所有点、总边权最小(或判连通)。给的是边表、m 不大。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 排序后从小到大加边,find 不同才合并(避免成环)。
  2. 别忘 for(i)fa[i]=i 初始化。
  3. 总权用 long long;判 cnt==n-1 确认连通。
限时自测P3366 模板 MSTP14080(八级真题,MST + LCA 路径最值,见 12)
4

Prim(朴素 O(n²))

MST · 稠密图
触发信号:点少(n≤1000)、边很多或直接给邻接矩阵。此时朴素 Prim 比 Kruskal 更顺手。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. dis[v] 是"v 到当前树的最短边",不是源点最短路(别和 Dijkstra 混)。
  2. 必须先 dis[1]=0 才能启动;累加 totlong long
  3. 选出的 udis[u]==INF,说明图不连通。
  4. 稀疏图(给边表)用 Kruskal;稠密图 / 邻接矩阵用朴素 Prim。
限时自测P3366(也可 Kruskal)/ P1546 最短网络(矩阵建图,Prim 自然)
5

并查集(独立应用)

连通 / 判环
触发信号:动态合并集合、判断两点是否连通、数连通块个数、无向图判环。是 Kruskal 的基础件,也常单独考。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 比较前都要 find 到根;判连通用 find(a)==find(b)
  2. 无向图判环:加边前两端已同根就会成环(Kruskal 同理)。
  3. 有向图判环不用并查集,用拓扑排序(见 6)。
限时自测:P3367 模板并查集 → 嵌入 P14080 Kruskal
6

拓扑排序 + DAG 上 DP

有向图
触发信号:有向图——求合法顺序 / 判有向图是否有环 / 在 DAG 上做 DP(最长路、计数、"转移就是边"的隐式图)。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 判环看入队总数order.size())是否 <n
  2. DAG-DP 必须按拓扑序转移,保证 uv 先算完。
  3. 只在 --indeg[v]==0 时入队,别重复入队。
限时自测P11380 有向图判环P10726 隐式图 DAG-DP / P15804 消息查找

二、组合 / 计数

7

杨辉三角递推求组合数

无需逆元 · 最稳
触发信号:要 C(n,m),n、m 不大(≤2000~5000);模数可能不是质数。最不易错的求组合数法。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 边界 C(i,0)=1;内层只算 j<=i
  2. 纯加法、不涉及除法,模数不是质数也能用
  3. n 很大(>5000)打不下 O(n²) 表时,才改用阶乘+逆元(见 8)。
限时自测P2822 组合数问题(杨辉三角+前缀和)/ P3414 组合数
8

阶乘 + 乘法逆元(大组合数取模)

质数模
触发信号:求 C(n,m)/排列数/方案数,n 很大(1e5+),对质数(如 1e9+7)取模,式子里有除法/阶乘。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 模意义下"除以 x" = 乘 inv(x)=x^(MOD-2),前提 MOD 是质数
  2. 看清模数:若是 1e9(非质数)不能用费马逆元,改杨辉三角递推或多重集直接连乘整除
  3. 全程 long long + 随时取模。
📐 逆元与费马小定理(为什么能"模意义下做除法")

逆元:模 p 下没有除法。要"除以 a"就乘 a 的逆元 inv(a),它满足 a · inv(a) ≡ 1 (mod p)。组合数 C(n,m)=n!/(m!(n-m)!) 带除法,于是把 ÷m! 换成 ×inv(m!)

费马小定理:p 是质数、且 a 不是 p 的倍数时,a^(p-1) ≡ 1 (mod p)。两边同除以 a 得 a^(p-2) ≡ a^(-1) (mod p),所以 inv(a) = a^(p-2) mod p(用快速幂算,见模板 10)。

前提:p 必须是质数。p 非质数(如 1e9)时费马失效,改用杨辉三角递推(模板 7)或多重集直接整除。

其它求法:扩展欧几里得(只要 gcd(a,p)=1,不要求 p 质数);批量求 1..n 的逆元用线性递推 inv[i] = (p - (p/i)*inv[p%i]%p) % p

约数 / 倍数计数(调和级数):把每个数的贡献加给它的倍数 for(d=1;d<=K;d++) for(m=d;m<=K;m+=d) cnt[m]+=...;,复杂度 O(K log K)。P10263 因数统计就是这套路。
限时自测P10112 奖品分配(多重集排列+逆元)→ P13020 遍历计数

三、倍增(八级最值钱的一类)

倍增是框架,不是单个模板

核心递推 f[i][j] = f[f[i][j-1]][j-1](跳 2^j = 先跳两次 2^(j-1));查询时从高位 j 往低位 0 试跳,能跳就跳。五种考法:① LCA / k 级祖先 ② 快速幂 ③ 序列/状态跳跃 ④ 路径最值 ⑤ ST 表。本质都是"按 2 的幂翻倍"。

9

树上倍增:LCA / k 级祖先 / 路径距离

触发信号:树上多次问两点的公共祖先 / 两点距离 / 第 k 级祖先 / 路径相关。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 同步上跳条件是 up[a][j]!=up[b][j](不相等才跳),最后返回 up[a][0]
  2. 先对齐深度,相等要直接返回(题目不保证 a≠b)。
  3. 树上两点距离 = dep[a]+dep[b]-2*dep[lca(a,b)](常考,背下来)。
  4. k 级祖先就是把 k 拆二进制按位跳;"对齐深度"本质就是跳 dep[a]-dep[b] 级祖先。
限时自测P3379 模板 LCA → P10289 LCA+最短路 / P13019 树上旅行
10

快速幂(指数倍增)

触发信号:求 a^b mod p(b 很大);也是求乘法逆元的基础(inv(x)=power(x,MOD-2))。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 每轮 a=a*a 是"底数翻倍 → 对应指数的 2 的幂",和 LCA 的 up 翻倍同构。
  2. 全程取模 + long long 防溢出;结果 r 初值为 1。
  3. 求逆元:MOD 是质数时 inv(x)=power(x,MOD-2)(费马小定理,见 8)。
限时自测:嵌入 P10112 / P2822(逆元、组合数取模)
11

序列 / 状态倍增跳跃

触发信号:有确定性转移"从 i 一步到 nxt[i]",要快速求"从 i 连跳多步到哪 / 在限制内能跳几步"。接竹竿、宝石项链、国旗计划全是这型。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 哨兵必须设全:所有"走不动"的位置(含末尾 n+1、n+2)都让 f[][0] 指向哨兵,否则会跳进 0 号下标把 2^k 全加上(宝石项链样例会算出 26 万而非 3)。
  2. nxt[i] 常用双指针(宝石项链:先求每个起点最短合法段)或倒序扫记录上次出现(接竹竿)预处理。
  3. 环形先破环成链开 2n,数组和 LOG 都要够大。
限时自测P10264 接竹竿(状态跳跃)→ P14924 宝石项链(破环+双指针+倍增)
12

倍增维护路径最值(LCA 上挂信息)

触发信号:树上两点路径的最大边 / 最小边 / 边权和,多次询问。删边重连 MST、货车运输都是这型。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 跳的同时更新答案:对齐深度、同步上跳两段,每次上跳前都要把 mx[][j] 取进 res
  2. 最后两条到 LCA 的边 mx[a][0]mx[b][0] 不能漏。
  3. 与 LCA 共用 up[][],只多开一个 mx[][];边权挂在子节点。
限时自测P14080 最小生成树(删边重连,八级真题)→ P1967 货车运输
13

ST 表(静态区间最值,O(1) 查询)

触发信号:数组不修改、多次问区间 max/min/gcd。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 右块起点是 r-(1<<k)+1(贴右端),别写成 l+(1<<k)
  2. "可重叠"只对 max/min/gcd 成立,求和不能用(用前缀和)。
  3. 询问极多时配快读。
限时自测P3865 模板 ST 表

四、树形 DP / 树上技巧

14

树形 DP(树的直径 / 子树合并)

触发信号:树上求最长链 / 最远点对 / 选或不选的最优,靠"向下最长 + 次长"拼。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 过 u 的路径 = d1+d2+1(两条向下链 + u 自己);返回只给父亲 d1+1
  2. 森林(多连通块)要靠 vis[] 标记,对每个未访问根各跑一次 dfs
  3. 有约束(如颜色不同才连)时,只在满足约束的子节点更新 d1/d2。
  4. 边数=节点数-1,注意题目要的是节点数还是边数。
15

树上差分(点差分 / 边差分)

触发信号:多次"对树上一条路径 u→v 整体加值",最后查每个点/每条边的累计值。配 LCA 用(见 9)。
C++14
✍️ 默写中点此显示骨架对照
易错点
  1. 点差分扣 fa[L],边差分扣 2*L——两者端点扣法不同。
  2. 需先建好 LCA(共用模板 9 的 updepfa)。
  3. 边差分把边的值记在"深的那个端点"上,根节点不对应任何边。
限时自测P3128 Max Flow P(树上差分+LCA)/ P11967 割裂

附 · 补充与节奏

高精度(偶尔配套)

需要输出不取模的精确大整数时(如 P1037 产生数),用 vector<int> 存每一位(低位在前)写高精度乘法 / 加法。日常计数题能取模就取模,能不用高精度尽量不用

最后 5 天默写节奏(建议)
默写模板限时自测(≤40 分钟/题)
6/22图论·最短路(Floyd / Dijkstra)B3647 / P10726
6/23图论·MST(Kruskal / Prim)+ 并查集 + 拓扑/DAGP3366 / P14080 / P11380
6/24倍增(LCA / 快速幂 / 序列 / 路径)+ ST 表P3379 / P14924 / P3865
6/25组合(杨辉三角 / 逆元)+ 树形 DP + 树上差分P2822 / P10112 / P11251 / P3128
6/26全部盖住各默 1 遍订正 / 重写 6/25 模拟中暴露的 2 个核心函数,不再新开陌生题
过关标准 每个模板能在 15 分钟内合上清单默写出可编译骨架,自测题能在 40 分钟内 AC。做到这个程度,八级两道编程题至少稳拿一道满分 + 一道大部分分,配上客观题,过线无忧。

GESP8 · 八级编程模板默写清单 · C++14 · 离线可用