news 2026/10/20 8:17:56

ACM题集整理与解题源码沉淀:从资源收藏到高效训练

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ACM题集整理与解题源码沉淀:从资源收藏到高效训练

简介:面向ACM竞赛学员与算法学习者的题集汇总包,集中整理了大量训练题目及对应解题源码,覆盖数据结构、图论、动态规划、字符串处理、数学与贪心算法等核心竞赛知识点,既适合入门者系统学习,也便于参赛选手赛前刷题复盘。压缩包共281个文件,以50个cpp解题源码为核心,搭配81个vsidx、44个suo、44个db等Visual Studio工程辅助文件,以及33个ipch缓存和2个txt说明,整体约870.44MB,文件目录按题目或专题组织,可直接打开工程查看完整代码与调用关系。目前已有878人学习下载,源码源于参赛者与教练团队的实战积累,通过阅读分析可学习高效编码技巧、状态转移设计及搜索剪枝等优化策略,对系统备赛和提升编程思维很有帮助。对于每个问题,还可对照源码研究解题思路与时间复杂度优化,形成自己的算法模板。

1. 超多 ACM 题集汇总,但真正缺的是筛选标准和解题源码

带过几轮 ACM 新人之后,我越来越觉得“题集”这词被用滥了。硬盘里躺着几百 MB 的 ACM 题集汇总,资源包里题目编号从几百到几千,文件名有中文有英文,有的还嵌套着三层压缩包,真正打开之后反而不知道从哪道题入手。当年我也干过这种事:见到超多 ACM 题集汇总就下载,下完解压、收藏、再也没打开过。直到后来接手某高校算法兴趣小组的训练,被迫从零整理一套能每周推进的题集,才摸清楚这里面哪些是体力活、哪些是真本事。

这标题看起来是“题目多、源码全”,但落到日常训练里,核心矛盾从来不是题量,而是筛选标准和复现成本。题量再多,没有难度曲线、没有主题归类、没有能本地跑通的解题源码,就只能躺在磁盘里当数字藏品。反过来,哪怕只有百来道题,只要每道题有可验证的源码、有复杂度说明、有踩坑记录,它就是一支能出成绩的队伍的地基。这篇文章就把我从零整理 ACM 训练题集、沉淀解题源码的完整路径讲清楚,覆盖选型、目录组织、代码规范、复盘方法和五个最烦人的坑。

2. 题集资源这么多:先分清四种“ACM 题集”再决定要不要收藏

2.1 按来源分:OJ 静态导出、离线题包、训练题单、书籍配套源码

接触 ACM 题集汇总的第一步,是把“题集”这个词拆开。站在训练角度,我见过四种形态,每种的价值和坑完全不一样。

第一种是 OJ 静态导出。这类通常是把某个在线评测系统的题目按 ID 或标签抓取下来,存成 HTML、PDF 或者 JSON。优点是量大,动辄几千道,题目描述、输入输出样例都齐全;缺点是绝大多数没有配套数据,而且排版依赖原站样式,离线打开经常是乱码。某老牌 OJ 的早期导出包里还用 GB2312 编码,在 UTF-8 终端里全是“锟斤拷”,光清洗字符就够喝一壶。

第二种是离线题包,常见于各种“几千题打包下载”的资源目录。结构一般是题面/、源码/、数据/三个顶层文件夹,数据里有 in/out 文件。这是最接近“能练”的形态,但质量极不稳定。我见过题面和源码对不上的,见过两个不同年代的题目共用同一个编号的,数据也常缺边界用例。这种包适合当原料库,不适合直接导学。

第三种是训练题单。这是有经验的人按主题和难度排好的题目序列,比如“动态规划从入门到放弃 100 题”,每道题给出来源、难度、推荐理由。题单的信息密度最高,因为筛选成本和序关系已经由别人替你完成了。有名的题单通常在社区里被反复转发,但问题是维护节奏慢,部分题面链接已经失效,需要自己跳跃式地核对。

第四种是书籍配套源码。比如某算法经典教材每一章后面的习题实现,或者一本 ACM 入门书的示例代码合集。这类题集的价值不在题面而在代码:它们的源码往往注释规范、命名清晰,适合当作“解题源码”的参照标准。缺点是难度梯度往往不够竞赛化,和真正 OJ 上的提交还隔着一层平台适配。

把这四种形态摆在一个表里,选型思路就清楚了:

题集形态典型内容优点主要问题适合用途
OJ 静态导出题面 HTML / PDF量大、覆盖全无数据、无源码、排版乱初期大规模筛题
离线题包题面 + 数据 + 源码最完整的训练闭环编号错位、数据不全本地刷题原料库
训练题单有序号的题目列表难度曲线清晰链接失效、缺乏代码制定每周训练计划
书籍配套源码章节例题代码注释规范难度平稳、量少学习标准写法和思想

2.2 拿到“超多题集汇总”后,我做的第一件事是抽稀有度

下载完任何一份 ACM 训练题集汇总,别急着开刷,也别急着全量导入。我一般会先写一个扫描脚本,把目录结构和文件类型过一遍,目标是回答三个问题:里面到底有多少独立题目?每道题是否同时具备题面、数据、源码三个要素?难度和主题的标注是怎样的?

这一步相当于给题集做“稀有度鉴定”。一千道纯题面一题源码都没有的包,价值远低于三百道带数据带注释的包。很多所谓“超多 ACM 题集汇总”其实就是 OJ 导出加一层目录封装,真正能把“数据 + 源码 + 题面”三件套对齐的,百不存一。我通常用一个简单的 Python 脚本快速给出统计报告:

import os from collections import defaultdict root = "/path/to/acm_problem_set" ext_map = defaultdict(int) name_index = defaultdict(set) for dirpath, dirnames, filenames in os.walk(root): for fname in filenames: ext = os.path.splitext(fname)[1].lower() ext_map[ext] += 1 # 按文件主名聚合,判断同一道题是否齐了三件套 key = os.path.splitext(fname)[0] name_index[key].add(ext) print("扩展名统计:", dict(ext_map)) complete = {k: v for k, v in name_index.items() if {".md", ".in", ".out", ".cpp"} <= v} print(f"题面/数据/源码齐全的题目数: {len(complete)}")

这段代码的意义不是跑完就完,而是给你一个可量化的质量门槛。参数上可以自定义root指向任意题集根目录,ext_map统计了文件夹里有哪些类型的文件,name_index按主文件名聚合了扩展名集合。判断“齐全”的标准是同时存在.md题面、.in输入数据、.out输出数据和.cpp源码,这个集合可以根据实际场景放宽,比如有些题集用.txt存题面,那就把.md换成.txt。

跑完之后最常见的结论是:看起来两千题的汇总,三件套齐全的不超过一百。这时候千万别灰心,这一百题其实就是最值得先投入的种子题集。其余的题目数据,要么等后续补数据,要么只用来做读题训练。筛选过程本身就是训练,比盲目刷题有价值得多。

2.3 为什么多数人“题集一堆、成绩没有”:收藏不等于训练

ACM 训练里有个顽疾,叫“资源收藏症”。看见超多 ACM 题集汇总就保存,保存完觉得已经拥有了这些题,然后又去搜下一份。实际上刷题生涯的进展不取决于磁盘里题目数量,而取决于每周提交次数和复盘深度。我见过某开发者收藏了十几个“ACM 题集汇总”包,但三个月内提交记录不到 30 次;也见过 A 同学手里只有三百题的整理集,每周固定提交十条,半年后区域赛铜牌线附近。

所以题集汇总的正确用法是“矿源”,不是“进度”。它的任务是让你在同一主题下能找到足够多的同类题做变式训练,而不是让你沉迷于整理文件本身。我的建议是:拿到新题集,先按 2.2 的脚本做粗筛,把三件套齐全的题挑出来,再按主题归类,然后立刻删掉原始大包在工作目录里的副本,只保留整理后的结构。用不上的一律不留在当前工作区,否则目录一深,连自己都找不到题。

3. 用手建一个可滚动的训练题集工程:目录规范、统一模板与验证脚本

3.1 按主题与难度组织的目录结构:一套能持续回填的框架

从零搭训练题集,最忌讳边下边乱塞。我的习惯是先定死目录骨架,后续所有题目都按规则填进去。规则很简单,顶层按算法主题分,二级按难度分,题目录里固定放题面、源码、笔记三个文件。下面是一套经过多次调整、目前小组内共用并且能滚动的结构:

acm_training/ ├── search/ │ ├── easy/ │ │ ├── P1001_permutation/ │ │ │ ├── problem.md │ │ │ ├── solution.cpp │ │ │ └── notes.md │ ├── medium/ │ └── hard/ ├── dp/ ├── graph/ ├── math/ ├── string/ ├── data_structure/ ├── scripts/ │ ├── init_problem.sh │ ├── gen_test.py │ └── stat_progress.py └── README.md

主题目录用什么英文名取决于团队习惯,但建议和 OJ 的 tag 体系保持一致,比如动态规划就叫dp,图论就叫graph,搜索就叫search。二级难度我固定用easy / medium / hard,不需要更细。再往下是单题的目录,命名格式统一为编号_英文简短名,编号直接用原题来源的题目 ID,避免重名。

这个结构的好处是两层:第一,新题加入时决策成本极低,看到主题和难度就知道该塞进哪个目录;第二,脚本工具可以对整个树做批量统计,比如某个主题下有多少 easy 题没写 notes,哪个难度区间已经饱和。对容易迷失在海量题集里的新人来说,这种结构像是一个外置大脑,什么时候该刷什么都一目了然。

3.2 一键新建题目目录:初始化脚本的写法与参数含义

有了骨架,得配一个初始化脚本,让“加一道新题”从五分钟变成五秒钟。这个脚本做的事情是:解析题目编号和题目名,创建目录,生成三份文件的模板,并且在README.md的对应主题表里追加一行记录。工具用 bash 就能写,但要注意参数校验,避免用户手滑建出奇怪目录。

#!/usr/bin/env bash # 用法: ./init_problem.sh <topic> <difficulty> <problem_id> <short_name> set -euo pipefail TOPIC="$1" DIFF="$2" PID="$3" NAME="$4" BASE="$(dirname "$0")/.." DIR="$BASE/$TOPIC/$DIFF/${PID}_${NAME}" if [[ ! -d "$DIR" ]]; then mkdir -p "$DIR" else echo "目录已存在: $DIR" exit 1 fi cat > "$DIR/problem.md" <<EOF # $PID $NAME ## 来源 ## 题意 ## 输入输出格式 ## 样例 EOF cat > "$DIR/solution.cpp" <<'EOF' #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); // TODO: 在这里写解题代码 return 0; } EOF cat > "$DIR/notes.md" <<EOF # $PID 笔记 ## 思路 ## 复杂度 ## 踩坑 EOF echo "题目初始化完成: $DIR"

这里有几个参数值得说清楚。TOPIC和DIFF必须和目录骨架里存在的值一致,拼错的话题目会落到一个孤儿目录,后期统计时出现数据空洞。PID是原题 ID,保留它的价值在于日后回溯到 OJ 页面查讨论区,所以不要自作主张改成自增序号。short_name用英文或拼音都行,但要避免空格和特殊字符,否则后续写文件路径时会踩转义坑。

代码模板我用的是bits/stdc++.h加ios::sync_with_stdio(false),这个组合是竞赛提交的标准写法,能省去大量 include 行并关闭 C 风格 IO 同步,避免 cin/cout 在数据量大时慢到超时。不过要提醒你,这套写法只在支持 GNU C++ 的评测机上是安全的,如果将来要在某一类只提供 MSVC 的环境编译,就得改成常规 include 组。模板里的TODO是刻意留下的,倒逼解题前先读题再落笔,而不是顺手复制粘贴旧代码。

3.3 验证源码能否本地跑通:造数据脚本和 diff 检查

题集汇总里的“解题源码”有一个致命问题:很多代码贴出来能过样例,但一跑你自己的测试数据就崩。所以任何源码进入题库之前,必须过一遍本地验证。常用的做法是给每道题配一个生成器,用随机数据做冒烟测试,至少验证输入输出格式正确、程序不超时不崩溃。下面是一个 python 生成器的示例,按题意生成 n 与数组,喂给编译好的二进制,并比对期望结果:

import random import subprocess import sys n = random.randint(1, 100000) print(n) arr = [str(random.randint(-10**9, 10**9)) for _ in range(n)] print(" ".join(arr))

这段随机生成器本身不是一个完整程序,只是一个片段。完整做法是让生成器产出输入文件test.in,然后用./solution < test.in > test.out跑出结果,再和暴力版程序的结果做 diff。参数说明上,n的范围要贴合题目约束,arr的取值范围也要按题意来,否则你用 1e9 的数据测试本来就不允许负数的题,没意义。真正重要的其实不是比对全部随机数据,而是提前写一个暴力版本,保证小数据范围内正确性可判定。

3.4 统一源码写法:可读性优先还是速度优先

题集汇总里的源码风格千差万别,有的喜欢把数组开成全局变量,有的习惯用 struct 封装,有的写满位运算看起来炫技实际难读。我所在的算法小组内部约定:收录到题库里的源码统一走“可读性优先,速度次之”的路线。这不是说性能不重要,而是当源码要被五个人反复阅读时,清晰的变量名和注释省下的时间远大于微优化那几毫秒。

统一的模板包含三个要素:头部注释说明题目来源和算法思路,核心函数的命名用完整单词,复杂度的推导写在函数注释里。下面这段代码符合我们的约定,也适合作为题集源码的一个范本:

// Problem: P1001 全排列生成 // Algorithm: 回溯法 // Complexity: O(n!) #include <bits/stdc++.h> using namespace std; int n; vector<int> path; vector<bool> used; void dfs(int depth) { if (depth == n) { for (int i = 0; i < n; i++) { cout << path[i] << (i + 1 == n ? '\n' : ' '); } return; } for (int i = 1; i <= n; i++) { if (used[i]) continue; used[i] = true; path.push_back(i); dfs(depth + 1); path.pop_back(); used[i] = false; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; used.assign(n + 1, false); dfs(0); return 0; }

这段代码的逻辑很直白:used数组标记数字是否用过,path保存当前排列,dfs在深度达到n时输出一组排列。复杂度假设计是当前节点的分支枚举,回溯撤销操作保证每个排列只生成一次。对初学者来说,这种源码能直接当作“什么是标准回溯”的参照物;对于熟手,改造成字典序生成或非递归版也容易下刀。收进题库的源码都应该达到这个水平,那些一次提交就过但变量名全是一两个字母的代码,建议只留在自己提交记录里,不要进题库共享目录。

4. 解题源码沉淀为可复用的训练资产:笔记格式、进度统计与批量回滚

4.1 每道题配一份 notes:像代码评审一样写做题记录

如果一份题集里的源码只有代码没有笔记,那还只是半成品。我要求训练集里每道题都必须有notes.md,格式固定为三段:思路、复杂度、踩坑。这道工序一开始会显得拖慢速度,但它是把“做过的题”变成“自己的题”的关键一步。

思路部分写两三句话即可,重点是让一个月后的自己看到这几行字能想起来当时怎么切入的。复杂度部分必须写时间复杂度和空间复杂度,而且要具体到O(n log n)而非笼统的“很快”。踩坑部分写最让自己痛的细节,比如“边界条件是 k=0 时要直接输出原数组”“树是链状时递归会爆栈,要改迭代”。这些内容就是题集里最珍贵的信息差,外面找不到,只能自己做题做出来。

4.2 写一个进度统计脚本:把题集从静态文件夹变成数据看板

题目数量积累到两三百之后,光靠人脑记进度已经不现实。我会在scripts/下放一个stat_progress.py,遍历目录树,统计每个主题下的题目数、有源码数、有笔记数,再算出“可复习”比率。这样每周训练结束后跑一次,就能看到哪些主题已经饱和、哪些主题还欠债。

import os from collections import defaultdict root = "../" stats = defaultdict(lambda: {"total": 0, "has_src": 0, "has_notes": 0}) for dirpath, dirnames, filenames in os.walk(root): if "problem.md" not in filenames: continue rel = os.path.relpath(dirpath, root) parts = rel.split(os.sep) topic, diff = parts[0], parts[1] stats[topic]["total"] += 1 stats[topic]["has_src"] += "solution.cpp" in filenames stats[topic]["has_notes"] += "notes.md" in filenames for topic, cnt in sorted(stats.items()): print(f"{topic}: total={cnt['total']}, src={cnt['has_src']}, notes={cnt['has_notes']}")

参数说明:root指向题集根目录,或者直接保存到scripts/下用../指回上级目录。这个脚本按两层目录解析topic和diff,所以如果目录结构不规范,统计就会错位。它不要求所有题都齐三件套,而是明确暴露缺口,方便下一阶段集中补齐。

跑完这个脚本之后,你会自然进入一个补墙循环:哪个主题源码缺失多,就去补哪里的题;哪个主题笔记缺失多,就去复盘哪里的代码。题集的“汇总”价值就体现在这里——它不是终点,而是你训练闭环里的数据底座。

4.3 批量比对源码风格:从题集汇总里剔除“伪源码”

题集汇总里有一类文件很能迷惑人:文件名是.cpp,打开之后其实是题面或者半成品,编译根本不过。这种“伪源码”会污染整个题集的质量。解决的办法是加一个编译冒烟脚本,批量对每个目录下的solution.cpp执行一次编译,失败的直接标记出来。

#!/usr/bin/env bash # 编译冒烟测试,找出题集中无法通过编译的源码 set -u for cpp in $(find .. -name "solution.cpp"); do dir="$(dirname "$cpp")" if g++ -std=c++17 -O2 -w "$cpp" -o /tmp/test_bin 2>/tmp/compile_err; then echo "OK: $cpp" else echo "FAIL: $cpp" head -n 5 /tmp/compile_err fi done

这段脚本的核心参数是-std=c++17和-O2。-std=c++17设定了语言标准,不同 OJ 的版本从 C++11 到 C++17 不等,你的题集源码最好统一按一个标准维护,否则换平台编译就翻车。-O2是竞赛评测的常规优化等级,有些源码在-O2下会有未定义行为警告,这里能用编译冒烟敲打出来也可以提前规避。-w是为了不刷屏警告信息,只留错误。实际维护时,我会让这个脚本每周跑一次,保证题集里的源码随时可编译,而不是囤到赛前才发现全是历史遗留问题。

4.4 复盘日怎么用题集:每周半天的“清账”

题集里题目越积越多以后,真正让它产生复利的是定期复盘。我习惯每周抽半天做清账:先跑 4.2 的进度脚本看缺口,再挑当前训练主题相关的十道已做题,重新看一遍源码,把 notes 里的踩坑标记更新一遍。这个过程看起来是重复劳动,实际上是在把短期记忆转成长时记忆。比如动态规划里“状态定义不清导致转移方程推不下去”这类问题,第一次记录和第三次复盘记录完全不一样,第三次你往往能提炼出预防性的检查清单。题集汇总的意义就是让这些题目留在原地,而不是刷完就丢进记忆黑洞。

5. 避坑:整理 ACM 训练题集与源码最容易踩的五个大坑

5.1 坑:题目带的是“样例数据”而不是“评测数据”,本地能跑但一交就错

现象:从题集里挑了一道题,本地拿样例测试完全正常,甚至自己构造了几组数据也通过,提交到 OJ 却WA或者RE。

原因:题集汇总里的.in/.out很多是从题目页面扒下来的样例数据,不是隐藏评测数据。样例数据的作用只是格式演示,覆盖不到边界条件,比如n=0、图不连通、数字溢出。有些题集声称带了完整数据,实际也只是部分随机数据,强度不足以验证源码正确性。

解决:把对外来数据的信任级别降为“冒烟测试数据”。关键题目配上暴力解法做对拍,在n较小的范围内随机生成数据,用两种实现分别跑结果并比对输出。对拍次数跑个几百上千组,正确性才算有了基础保障。生成器和暴力代码可以单独放在scripts/gen_test.py和scripts/brute.cpp里,不要和题解源码混在一起,免得提交时带了非法文件。

5.2 坑:题集编码混乱,Windows 打包、Linux 打开全是乱码

现象:解压某份题集汇总后,problem.md打开是“锟斤拷”,源码里的中文注释全是问号,代码能看懂但没法用。

原因:很多离线题集是 Windows 环境下打包的,文本用 GBK 或 GB2312 编码存储。Linux 终端默认 UTF-8,解码失败。更麻烦的是文件内混着多种编码,批量转换很容易误伤已经正常的文件。

解决:不要手工转换,用批量命令扫一遍全部文本文件,检测编码再统一转 UTF-8。常规做法是先用file -i查看编码分布,再用iconv批量转码。如果题集里有少部分本来就是 UTF-8 的文件,转换前先加过滤。转完之后跑一遍 4.3 的编译冒烟测试,确保源码注释转换没把字符串搞坏。

#!/usr/bin/env bash # 将题集目录下所有 .md 和 .cpp 转为 UTF-8 find .. -type f \( -name "*.md" -o -name "*.cpp" \) -print0 | while IFS= read -r -d '' f; do enc=$(file -b --mime-encoding "$f") if [[ "$enc" == "iso-8859-1" || "$enc" == "unknown-8bit" ]]; then iconv -f GBK -t UTF-8 "$f" > "$f.tmp" && mv "$f.tmp" "$f" echo "converted: $f" fi done

这个脚本里的file -b --mime-encoding用来探测实际编码,GBK 编码经常被识别成iso-8859-1或unknown-8bit,所以这两个分支都要处理。iconv从 GBK 转到 UTF-8,输出先落到临时文件再覆盖,避免原文件损坏。执行之前记得先把整个题集备份,我吃过一次亏:转码脚本把源码里的某些双字节字符替换成了问号,导致整包代码全部编译失败,备份就是后悔药。

5.3 坑:同一题集里源码语言混乱,C++03 和 C++17 的代码混在一起

现象:题集里一百道题的源码,有的用了auto,有的还是for (int i = 0; i < n; i++),有的用printf,有的用cin。拿到本地统一用-std=c++17编译的时候,混着 C++03 风格的部分也能编过,但一旦涉及tr1库或旧式__builtin,新版编译器行为说变就变。

原因:截取自不同时期、不同 OJ 的代码,风格和依赖的编译器版本不一致。题集汇总往往只是把它们堆在一起,没有做语言版本归一化。

解决:给题集的根目录写一个COMPILE_STANDARD.md,写明这些源码默认为 C++17,如果某个目录下的源码依赖旧标准,要在该目录的README.md里单独标注。更保险的是一劳永逸地把老代码升级到统一风格。实际操作中,我一般把老代码的printf/scanf保留,因为它们性能其实更好,但会把tr1相关 include 改掉。尽量别主动改算法逻辑,只改编译兼容性,否则容易顺手改挂。

5.4 坑:题集里的“超多题”以读题成本极高的长题面为主,刷不动

现象:看到一份“超多 ACM 题集汇总”,里面大量题目题面超过两页,背景故事长、输入输出格式藏在第五段落之后,训练时读题时间比写代码时间还长,两周就失去动力。

原因:这种题集追求“全”而不追求“练”。真实竞赛里确实有长题面题,但比例很低。入门和中期选手最需要的是题意清晰、考点明确的题,长题面对训练效率是负贡献。

解决:筛选题目时按题面长度做一次排序,优先刷题面短、格式明确的题。短题面不代表简单题,很多短题面是极致的思维题,对思维训练价值很高。等刷满一百题短题面后,再逐步引入中等长度的题面,最后过渡到真实区域赛的题面。这个过程本质上是“训练素材分级”,和刷题进阶是同一个节奏。

5.5 坑:源码能过题集自带数据,但没注意到题目来自不同 OJ,输出格式要求不同

现象:从别处复制的solution.cpp在你本地跑出的结果和题集里的.out一致,拿到真实 OJ 提交却Presentation Error或者Wrong Answer。

原因:不同 OJ 的判题输出规格不一样。有的是行末不能有多余空格,有的是最后一行必须换行,有的是大小写敏感,还有的要求按字典序输入。题集的.out文件参考的是导出源 OJ 的格式规范,你的验证环境未必能暴露这类差异。

解决:给每道题的problem.md头部记录来源 OJ 和格式注意点,例如“每行末尾无空格”“输出占一行”“大小写不敏感”这类说明。提交前自己写一个格式化函数,统一处理行尾空格和换行符,能规避大多数 PE 问题。另外养成一个好习惯:源码里输出部分用一个函数包住,任何格式调整只改那里,不改业务逻辑。

6. 把静态题集变成动态训练系统:错题本、随机抽题与模拟赛

题集整理到后期,真正的进阶不是再多收一两千道题,而是让这套静态目录自己长出“训练计划”。我最后分享三个我自己持续在用的玩法,都能在已有的题集目录上直接叠加上去,不需要重构。

第一个玩法是错题本目录。在题集根目录下加一个review/文件夹,里面按主题建文件,把每一道做错或者卡壳超过半小时的题目编号、错误原因、正确思路的关键词记下来。每周复盘时直接打开review/dp.md,就能看到自己最薄弱的状态定义容易错在哪。这个目录比题集本身更值钱,因为它是你解题历史的浓缩。

第二个玩法是随机抽题做模拟赛。写一个random_match.py,从指定难度区间里随机抽三道题,拉一个match_YYYYMMDD文件夹,把题目链接或本地路径放进去,然后按 2 小时倒计时自己模拟比赛。这种做法的价值在于强迫你在不熟悉题目顺序的前提下决策:先做哪道、放弃哪道、如何分配时间。水平越接近真实竞赛,这个模拟的含金量越高。

第三个玩法是变式改造。题集汇总里源码在精不在多,我会挑出十道经典题,每道题试着重写一遍:改成空间优化版、改成迭代版、改成输出方案版。这比做新题更能检验是否真正理解。比如全排列这道题,不仅能写回溯,还能写字典序生成,还能用next_permutation对比三种写法的时间差距。当你对一道题能做出三个版本并比较差异时,这道题才真正属于你了。

我自己在整理题集这条路上翻过不少车,最贵的一课是:收藏的超多题集如果没配上自己的复盘机制,那只是自我安慰。现在我只保留三件套齐全的题,每道题都强制写 notes,每周固定跑一次编译冒烟和数据统计。这种做法让我的训练节奏稳定了下来,也希望这篇文章能帮你少走一点弯路。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 8:17:52

RAG数据准备全流程:从文档解析到向量入库的实战指南

做 RAG 系统这么久&#xff0c;一个感受越来越深&#xff1a;很多人把精力放在换大模型、调提示词、调向量检索参数上&#xff0c;却忽略了整套系统真正的地基——数据准备。数据准备阶段不仅仅是把文件里的文本抽出来、切两刀、灌进向量库那么简单。喂给 RAG 的原料是什么质量…

作者头像 李华
网站建设 2026/10/20 8:17:36

36套网站源码包实操指南:从结构拆解到项目落地

简介&#xff1a;面向网页前端开发者和网站设计初学者&#xff0c;36个漂亮的各类型网站源代码是一份有代表性的前端布局案例合集&#xff0c;以HTML、CSS和JavaScript为核心&#xff0c;覆盖单页、多栏、瀑布流、网格等常见网站布局&#xff0c;帮助读者理解不同结构的实现思路…

作者头像 李华
网站建设 2026/10/20 8:16:10

算法偏见从检测到修复:信贷模型公平性优化完整实践

前阵子我们团队接手了一个信贷审批模型的优化工作。模型整体AUC大概0.87&#xff0c;准确率看着还行&#xff0c;但把预测结果按人群拆开一看&#xff0c;问题就出来了&#xff1a;某类用户的拒绝率比其他人群高出快三倍。这属于典型的模型偏见——它不是某个人拍脑袋设计的规则…

作者头像 李华
网站建设 2026/10/20 8:16:03

Pandas相关系数矩阵与Seaborn热图可视化实战

先说我自己的习惯&#xff1a;拿到一份 DataFrame&#xff0c;不管数据多大多小&#xff0c;第一时间把每列之间的相关关系算清楚、用热图画出来&#xff0c;是我一定会做的事。哪怕后面还会做更复杂的模型&#xff0c;这一张相关矩阵热图也永远是我判断变量关系的第一份地图。…

作者头像 李华
网站建设 2026/10/20 8:15:11

数据库运维常用脚本实战:从备份恢复到性能优化

入职这些年&#xff0c;我发现自己干得最多的活&#xff0c;不是写业务代码&#xff0c;也不是搭架构&#xff0c;而是跟一堆"数据库常用脚本"打交道。无论是帮业务部门查一条慢SQL&#xff0c;还是半夜被叫起来看主从延迟&#xff0c;手里没几个趁手的脚本&#xff…

作者头像 李华
网站建设 2026/10/20 8:15:03

翻译等变编码:给mRNA语言模型注入蛋白质翻译先验

1. 项目概述今年NeurIPS的榜单上&#xff0c;某研究组放出了一个叫Equi-mRNA的工作。标题全名是Protein Translation Equivariant Encoding for mRNA Language Models&#xff0c;简单翻译就是&#xff1a;给mRNA语言模型加一种“翻译等变”的编码方式&#xff0c;让模型在学序…

作者头像 李华