
简介本资源是专为蓝桥杯竞赛选手打造的QDUOJ适配题库面向算法初学者至进阶参赛者解决备赛过程中题目获取难、平台兼容性差、测试用例不全等痛点。压缩包共2个文件1个JSON题库数据文件、1个含多组输入输出的测试用例ZIP总大小70.24MB其中old_data.json结构化存储历年真题描述、约束条件与评测参数test_case.zip提供可直接导入QDUOJ的标准化测试集显著提升本地调试与平台提交的一致性。已有1366人学习下载实际覆盖蓝桥杯省赛/国赛高频考点包含完整题干解析逻辑、边界样例覆盖及QDUOJ特有判题适配说明助力用户快速熟悉赛制、验证代码鲁棒性并建立系统性刷题路径。1. 这不是又一个题库搬运工它把蓝桥杯真题塞进了 QDUOJ 内核跑起来就是一套可部署、可打分、可组赛的本地 OJ你有没有试过——下载一堆蓝桥杯历年真题 PDF手动建 Excel 记录学生提交、人工比对样例输出、用记事本改测试数据我去年带某高校校内选拔赛时就这么干过三天熬出黑眼圈还漏判了两份边界 case。直到发现这个「蓝桥杯题库 for QDUOJ修改版」它不是静态题集而是完整适配 QDUOJ v2.3 的可运行题库包含 127 道蓝桥杯省赛/国赛真题C/C/Java/Python 四语言每道题自带标准输入输出测试用例、时间/内存限制、多组样例自动比对逻辑甚至预置了蓝桥杯风格的题目分类标签填空题、编程题、大题拆解、难度星级★★★★★★和知识点映射递归、DP、图论、字符串处理。它面向的是真正要搭校内训练平台、组织模拟赛、做自动化评测的老师或竞赛教练——不是看题解的选手而是管题库的人。项目结构干净无外部依赖污染所有题目录入、判题规则、权限配置都走 QDUOJ 原生接口部署后直接进后台就能开赛。别被“修改版”三个字唬住它改得极克制只动题库导入脚本和判题配置模板QDUOJ 核心代码一行未碰升级兼容性反而比某些魔改版更强。2. 环境准备与部署从零拉起一个带蓝桥杯题库的 QDUOJ 实例2.1 确认基础环境QDUOJ 版本、系统依赖与数据库就位这个题库包不是独立服务而是 QDUOJ 的「题库插件」。它要求宿主 QDUOJ 版本 ≥ v2.3.0推荐 v2.4.2因为低版本缺少problem_importAPI 和多语言编译器配置项。我们不碰 Docker Compose 一键部署太黑盒出问题没法 debug而是走源码直装 题库注入路线全程可控。先确认你的服务器环境OSUbuntu 20.04 LTS 或 CentOS 7.9QDUOJ 官方 CI 测试基线Python3.8.10QDUOJ 后端要求别用 3.11psycopg2编译会翻车Node.js16.18.0前端构建用npm run build会卡在vue-template-compiler兼容性上PostgreSQL12.15必须MySQL 不支持 QDUOJ 的 JSONB 字段存测试用例Redis6.2.6会话与判题队列必需提示别用apt install python3默认版本Ubuntu 20.04 自带 3.8.10但 CentOS 7 默认是 2.7。用pyenv装指定版本最稳curl https://pyenv.run | bash export PYENV_ROOT$HOME/.pyenv export PATH$PYENV_ROOT/bin:$PATH eval $(pyenv init -) pyenv install 3.8.10 pyenv global 3.8.10数据库建库命令必须带UTF8和LC_COLLATE en_US.UTF-8否则中文题目描述会乱码CREATE DATABASE qduoj WITH OWNER qduoj_user ENCODING UTF8 LC_COLLATE en_US.UTF-8 LC_CTYPE en_US.UTF-8;2.2 拉取并初始化 QDUOJ 主体代码别用 GitHub 上那个 star 最高的 fork它混了大量未合入上游的私有补丁。我们用官方维护分支git clone --branch v2.4.2 https://github.com/QingDaoUOJ/QDUOJ.git cd QDUOJ # 安装 Python 依赖注意requirements.txt 里 psycopg2-binary 是坑必须源码编译 pip install -r requirements.txt --no-binary psycopg2 # 初始化数据库表结构 python manage.py migrate # 创建超级管理员后面进后台要用 python manage.py createsuperuser关键点migrate前确保settings.py中DATABASES配置正确且 PostgreSQL 用户已授权。如果报relation auth_user does not exist说明 migration 没跑全删掉migrations/下除__init__.py外所有文件再migrate。2.3 题库包结构解析看清这 127 道题是怎么“塞进去”的你下载的「蓝桥杯题库 for QDUOJ修改版」压缩包解压后是这样的bluebridge-qduoj/ ├── import_script/ # 核心题库导入脚本 │ ├── import_problems.py # 主入口读取 JSON 题目数据并调用 API │ └── problem_data/ # 所有题目原始数据JSON 格式 │ ├── basic/ # 基础题32 道 │ ├── algorithm/ # 算法题58 道 │ └── advanced/ # 高阶题37 道 ├── static_resources/ # 静态资源题目图、特殊输入文件 │ └── images/ ├── config/ # QDUOJ 配置增强项 │ └── bluebridge_settings.py # 注册蓝桥杯专用标签、难度映射规则 └── README.md # 仅说明导入步骤无技术细节重点在import_script/problem_data/下的 JSON 文件。打开一道典型题algorithm/2022_province_c_cpp_05.json结构长这样{ title: 砝码称重, description: 你有一架天平和 N 个砝码……, input_description: 第一行一个整数 N..., output_description: 输出一个整数表示能称出的不同重量个数。, time_limit: 1000, memory_limit: 262144, difficulty: 4, tags: [dp, 背包], languages: [c, cpp, java, python], test_cases: [ { input: 3\n1 3 9, output: 13 }, { input: 4\n1 2 4 8, output: 15 } ], sample_input: 3\n1 3 9, sample_output: 13, hint: 考虑用布尔数组 dp[i] 表示能否称出重量 i }注意三个实战关键字段time_limit单位是毫秒蓝桥杯 C/C 题常设 1000msJava/Python 设 2000msQDUOJ 判题机实际执行时会加 200ms 安全余量test_cases是数组QDUOJ 导入后自动生成对应数量的测试点每个点独立计时计内存languages字段决定该题在前端显示哪些语言切换 Tab不在此列表的语言提交会被前端直接拦截不是后端拒绝。2.4 执行题库导入用 Python 脚本把 JSON 批量喂给 QDUOJ API导入脚本import_script/import_problems.py是整个包的灵魂。它不操作数据库而是通过 QDUOJ 的/api/admin/problem/管理员 API 接口 POST 题目数据。这意味着你必须先登录 QDUOJ 后台拿到管理员 Cookie。先启动 QDUOJ 开发服务器# 在 QDUOJ 根目录下 python manage.py runserver 0.0.0.0:8000然后浏览器访问http://your-server-ip:8000/admin/login/用之前createsuperuser创建的账号登录。按 F12 打开开发者工具 → Application → Cookies复制sessionid的值一串 32 位 hex 字符。现在执行导入cd import_script # 安装 requests脚本依赖 pip install requests # 执行导入-u 指定 URL-s 指定 sessionid-d 指定数据目录 python import_problems.py \ -u http://localhost:8000 \ -s eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... \ -d ../problem_data/basic/脚本会逐个读取 JSON 文件构造 POST body发送到/api/admin/problem/。成功返回 HTTP 201失败则打印错误响应如{title:[此标题已存在]}—— 这就是避坑点。注意导入过程不校验题目重复性。如果同一道题同 title导入两次QDUOJ 会创建两个 ID 不同但内容相同的题目。后续管理麻烦建议首次导入前清空Problem表python manage.py shell -c from contest.models import Problem; Problem.objects.all().delete()。3. 题目配置与判题逻辑为什么蓝桥杯填空题也能自动判3.1 填空题的“伪判题”实现用标准输出匹配替代传统 AC 判定蓝桥杯真题里有大量填空题如“请填写 XXX 的值”这类题没有输入只需输出一个数字或字符串。QDUOJ 原生不支持“无输入题”但这个修改版用了一个巧妙的绕过方案把填空题的“答案”写死在test_cases[0].output里并设置input为空字符串。看一道填空题 JSON 示例basic/2021_province_c_cpp_01.json{ title: 空间, description: 小蓝准备用 256MB 的内存空间..., input_description: , output_description: 一个整数表示答案。, test_cases: [ { input: , output: 67108864 } ], sample_input: , sample_output: 67108864 }QDUOJ 判题机执行流程不变编译 → 运行传入空 stdin→ 捕获 stdout → 与test_cases[0].output比对。只要程序输出67108864无多余空格/换行即判 AC。这完全复刻了蓝桥杯官网填空题的判定逻辑——不关心算法只认最终答案。但这里埋了个雷Python 填空题如果写print(2**26)stdout 是67108864\n带换行而 JSON 里output是67108864无换行比对失败。解决方案有两个在 JSON 中把output写成67108864\n推荐统一风格或在bluebridge_settings.py中启用strip_output选项该包已内置判题时自动rstrip()提交代码的 stdout。3.2 多语言编译器配置让 Java 和 Python 也享受蓝桥杯真实环境QDUOJ 默认的 Java 编译器是javac -encoding UTF-8但蓝桥杯要求javac -encoding UTF-8 -source 1.8 -target 1.8强制 JDK 8 兼容。Python 默认用python3但蓝桥杯 Python 组限定pypy3提速且内存更稳。这些配置不在题目 JSON 里而在 QDUOJ 的全局设置中。你需要修改QDUOJ/settings/base.py# 在 JUDGE_SERVERS 配置块下方添加 JUDGE_LANGUAGES { c: { compile: {src_name: main.c, exe_name: main, max_cpu_time: 3000, max_real_time: 5000, compile_command: /usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors3 -stdc11 {src_path} -lm -o {exe_path}}, run: {command: {exe_path}, seccomp_rule: c} }, java: { compile: {src_name: Main.java, exe_name: Main, max_cpu_time: 4000, max_real_time: 8000, compile_command: /usr/bin/javac -encoding UTF-8 -source 1.8 -target 1.8 {src_path}}, run: {command: /usr/bin/java -cp {exe_path}:/tmp Main, seccomp_rule: java} }, python: { compile: {src_name: main.py, exe_name: main.py, max_cpu_time: 0, max_real_time: 0, compile_command: }, run: {command: /usr/bin/pypy3 {exe_path}, seccomp_rule: python} } }注意pypy3路径需which pypy3确认常见是/usr/bin/pypy3或/opt/pypy/bin/pypy3。如果没装apt install pypy3即可。别用python3蓝桥杯 Python 组明确禁用 CPython 解释器。3.3 难度与标签系统如何让教练一眼看出哪道题练 DPQDUOJ 原生只有difficulty数字字段1~5但蓝桥杯教练需要快速筛选“动态规划”“DFS/BFS”类题目。这个修改版在config/bluebridge_settings.py中注册了自定义标签体系# QDUOJ/settings/base.py 末尾追加 BLUEBRIDGE_TAGS { dp: {name: 动态规划, color: #FF6B6B}, dfs: {name: 深度优先搜索, color: #4ECDC4}, bfs: {name: 广度优先搜索, color: #45B7D1}, string: {name: 字符串处理, color: #96CEB4}, math: {name: 数学思维, color: #FFEAA7} }导入脚本import_problems.py会读取题目 JSON 中的tags字段如[dp, math]自动调用 QDUOJ 的/api/admin/tag/接口创建标签并关联到题目。效果是后台题目列表页会出现彩色标签前端题目详情页顶部显示动态规划 · 数学思维教练用标签筛选比翻页快十倍。4. 常见问题排查那些让你怀疑人生却只需改一行配置的坑4.1 现象导入脚本报错HTTP 403 Forbidden但管理员账号明明能登录后台原因QDUOJ 的 CSRF 保护机制默认开启。import_problems.py用requests直接 POST没携带csrf_tokenAPI 拒绝请求。解决在import_problems.py的session.post()前先 GET 一次/api/admin/problem/获取csrftokencookie再把它加到 headers# 在 import_problems.py 的 main 函数中 session.get(f{base_url}/api/admin/problem/) # 触发 CSRF token 设置 headers {X-CSRFToken: session.cookies.get(csrftoken)} session.post(f{base_url}/api/admin/problem/, jsondata, headersheaders)4.2 现象C/C 题目提交后一直显示 “Judging…”日志里看到Compile Error: /usr/bin/gcc: not found原因QDUOJ 判题机容器或宿主机没装 GCC。很多人只装了build-essential但忘了gcc包名在 Ubuntu 上是gccCentOS 上是gcc-c。解决Ubuntusudo apt install gcc gCentOSsudo yum install gcc gcc-c然后重启判题服务sudo systemctl restart qduoj-judge-server4.3 现象Python 题目提交后报Runtime Error日志显示ModuleNotFoundError: No module named numpy原因蓝桥杯 Python 组允许使用numpy但 QDUOJ 默认沙箱环境只装了标准库。pypy3沙箱路径/tmp/judge_env/下没装第三方包。解决在判题服务器上用pypy3 -m pip install numpy全局安装注意不是pip3是pypy3 -m pip。验证pypy3 -c import numpy; print(numpy.__version__)。4.4 现象题目详情页显示 “样例输入/输出” 正确但提交后所有测试点都是 WA检查发现test_cases里的output末尾多了\r\n原因Windows 编辑器保存 JSON 时用了 CRLF 换行Linux 判题机读取output字符串时包含\r比对失败。解决批量清理 JSON 文件换行符find ../problem_data -name *.json -exec sed -i s/\r$// {} \;或者更彻底用 Python 脚本重写所有 JSON强制用\nimport json for f in json_files: with open(f) as jf: data json.load(jf) for tc in data.get(test_cases, []): tc[output] tc[output].replace(\r\n, \n).replace(\r, \n) with open(f, w) as jf: json.dump(data, jf, indent2, ensure_asciiFalse)4.5 现象导入后题目列表里出现大量None标题点进去 404原因JSON 文件编码不是 UTF-8。比如用 GBK 编辑器保存的题目描述含中文import_problems.py用open(f, r)默认按系统编码读Linux 下是 UTF-8读 GBK 文件就乱码json.load()解析失败title字段变成None。解决在import_problems.py的load_json函数里强制指定编码def load_json(file_path): with open(file_path, r, encodingutf-8) as f: # 显式声明 return json.load(f)并确保所有 JSON 文件用 UTF-8 无 BOM 格式保存VS Code 右下角可切换。5. 二次开发实战给蓝桥杯题库加“智能推荐”功能5.1 需求场景学生总卡在同一类题上教练想按错误率动态推题某高校教练反馈学生反复错“DFS 剪枝”类题目但题库现有标签只能静态筛选无法根据实时错误数据推荐。我们需要一个轻量级推荐模块当学生 A 在题目 P 上连续 WA ≥ 3 次系统自动在首页推送同标签如dfs、同难度±1 星、AC 率 60% 的 3 道题。不碰 QDUOJ 核心只新增一个 Django Apprecommendercd QDUOJ python manage.py startapp recommender在recommender/models.py定义推荐规则from django.db import models from contest.models import Problem, Submission class RecommendationRule(models.Model): tag models.CharField(max_length20) # 对应 BLUEBRIDGE_TAGS 的 key difficulty_min models.IntegerField(default1) difficulty_max models.IntegerField(default5) max_ac_rate models.FloatField(default0.6) # 小于等于此值才推荐 created_at models.DateTimeField(auto_now_addTrue) class UserRecommendation(models.Model): user models.ForeignKey(user.UserProfile, on_deletemodels.CASCADE) problem models.ForeignKey(Problem, on_deletemodels.CASCADE) reason models.TextField() # 如 因在题目 迷宫 上连续 WA 3 次触发 created_at models.DateTimeField(auto_now_addTrue)5.2 关键逻辑监听提交事件触发推荐计算QDUOJ 的提交记录存在Submission模型中。我们在recommender/apps.py中监听post_save信号# recommender/apps.py from django.apps import AppConfig from django.db.models.signals import post_save class RecommenderConfig(AppConfig): default_auto_field django.db.models.BigAutoField name recommender def ready(self): from . import signals # 导入信号模块recommender/signals.py实现核心逻辑from django.db.models.signals import post_save from django.dispatch import receiver from contest.models import Submission, Problem from user.models import UserProfile from .models import UserRecommendation, RecommendationRule receiver(post_save, senderSubmission) def trigger_recommendation(sender, instance, created, **kwargs): if not created or instance.result ! Wrong Answer: return # 查该用户最近 3 次 WA 是否都在同一题 recent_wa Submission.objects.filter( user_idinstance.user_id, problem_idinstance.problem_id, resultWrong Answer ).order_by(-create_time)[:3] if recent_wa.count() 3: return # 获取题目标签一个题可能多个标签取第一个 problem instance.problem if not problem.tags.exists(): return first_tag problem.tags.first().name # 注意这里是 QDUOJ 原生 Tag 模型的 name 字段 # 查找匹配的推荐规则 rules RecommendationRule.objects.filter( tagfirst_tag, difficulty_min__lteproblem.difficulty, difficulty_max__gteproblem.difficulty, max_ac_rate__gteproblem.ac_rate # 题目 AC 率字段需提前在 Problem 模型加 ) if not rules.exists(): return # 推荐 3 道题排除当前题和已推荐过的 recommended_problems Problem.objects.filter( tags__namefirst_tag, difficulty__range(problem.difficulty-1, problem.difficulty1), ac_rate__ltrules.first().max_ac_rate ).exclude( idproblem.id ).exclude( id__inUserRecommendation.objects.filter(user_idinstance.user_id).values_list(problem_id, flatTrue) )[:3] for p in recommended_problems: UserRecommendation.objects.get_or_create( user_idinstance.user_id, problemp, defaults{reason: f因在题目 {problem.title} 上连续 WA 3 次触发} )注意Problem.ac_rate字段原生不存在需在contest/models.py的Problem类中添加ac_rate models.FloatField(default0.0, help_textAC 率由定时任务更新)并在admin.py中注册否则 Django Admin 看不见。5.3 前端集成在用户首页展示推荐题目QDUOJ 前端用 Vue首页模板在frontend/src/views/index/Index.vue。我们加一个推荐区块!-- frontend/src/views/index/Index.vue -- template !-- 原有内容 -- div v-ifrecommendations.length 0 classrecommend-section h3 为你推荐/h3 div classproblem-list router-link v-forr in recommendations :keyr.id :to/problem/${r.problem.id} classproblem-card div classtitle{{ r.problem.title }}/div div classmeta span classtag{{ r.problem.tags[0]?.name || 无标签 }}/span span classdifficulty★{{ r.problem.difficulty }}/span /div div classreason{{ r.reason }}/div /router-link /div /div /template script export default { data() { return { recommendations: [] } }, async mounted() { try { const res await this.$http.get(/api/recommendation/user/) this.recommendations res.data.results } catch (e) { console.error(加载推荐失败, e) } } } /script后端 API 在recommender/views.pyfrom rest_framework.views import APIView from rest_framework.response import Response from .models import UserRecommendation class UserRecommendationAPIView(APIView): def get(self, request): if not request.user.is_authenticated: return Response({results: []}) recs UserRecommendation.objects.filter( userrequest.user ).select_related(problem).order_by(-created_at)[:5] data [{ id: r.id, problem: { id: r.problem.id, title: r.problem.title, tags: [t.name for t in r.problem.tags.all()], difficulty: r.problem.difficulty }, reason: r.reason } for r in recs] return Response({results: data})最后在urls.py中注册路由# QDUOJ/urls.py urlpatterns [ path(api/recommendation/, include(recommender.urls)), ]5.4 部署与验证三步上线不用重启服务迁移数据库python manage.py makemigrations recommender python manage.py migrate收集静态文件Vue 前端cd frontend npm run build cd .. python manage.py collectstatic --noinput重启服务只需重启 Django判题机不用动sudo systemctl restart qduoj-web验证方法用测试账号提交一道题三次 WA刷新首页看是否出现推荐区块。日志里搜trigger_recommendation可确认信号是否触发。从那以后我每次给竞赛平台加新功能都强制走三步先写最小可行模型如只存推荐记录、再加触发逻辑信号监听、最后补前端Vue 组件。绝不一上来就画大饼搞“AI 推荐引擎”。因为真实场景里学生多点一次推荐链接比算法提升 0.5% 的准确率更有价值。希望帮到你。本文还有配套的精品资源点击获取