1. 蓝桥杯填空题的得分逻辑:先搞清楚它在考什么
1.1 填空题在整个赛制里处在什么位置
打过蓝桥杯的人都知道,卷子一翻开,前几道就是填空题。近几年省赛和国赛的常见编排是:卷首放两到三道填空题,单题分值通常在5分到10分之间,合计十几分到二十分不等,具体分值以当年赛题为准。剩下的编程题才是大头,但填空题的意义不只是那点分数,它决定了你开场的心态和后面题目的时间余量。
我见过太多选手,编程题做得七七八八,结果翻开卷子第一题填空花了二十五分钟,最后编程题没时间调。也见过相反的情况,填空两道题五分钟解决,心态稳得不行,后面越做越顺。所以"十秒快速做出填空题"这个说法,重点不在"十秒"这三个字玄学,而在于你有没有一套被反复验证过的识别流和工具流。看到题目,脑子里立刻弹出"这是日期类""这是枚举类""这是大数类",然后手或者代码跟上,答案出来。
还有一点常被忽略:填空题不判过程,只认最终提交的那个答案,整数就是整数,字符串就是字符串。这意味着你完全可以用本地编译器、计算器、表格软件、Python解释器去算,甚至手推公式——只要答案对就行。这个规则本身就是"快速解法"存在的土壤。
1.2 填空题和编程题的本质差异
理解差异是提速的前提。编程题要求你在时间与空间限制内通过所有测试点,考的是完整实现能力;填空题考的是"得到一个确定结果",考的是推理效率。这两件事的思维方式完全不同。
编程题里你不敢用三重循环枚举一亿次,但在填空题里,如果本地三秒钟能跑出结果,你完全可以这么干。编程题里你得考虑输入输出格式、多组数据、边界情况,填空题里这些全都不用管。所以很多在编程题上被卡住的人,填空反而做得飞快——因为他敢用"笨办法"。反过来,也有选手习惯性地想在填空题里写"优雅算法",结果推导半小时,不如直接枚举来得快。
提示:填空题的容忍度比分界线更宽,赛前就要给自己建立"能算出来就是好方法"的心态,不要为了优雅牺牲时间。
1.3 "十秒出答案"拆开看是什么
我个人把"十秒"理解成十秒之内完成三件事的判断:第一,这题的答案是什么类型(整数、字符串、还是带小数);第二,用哪种手段拿到它(手推、心算、写一小段代码);第三,大概会跑多久,要不要先放着换下一题。这三件事判断完了,真正执行可能是一分钟也可能是一毫秒,但你不会在错误的路径上浪费时间。
这个判断能力不是天生的,是靠题型积累堆出来的。下面这几类填空,基本覆盖了历年卷面上能见到的绝大多数,我把识别特征和解法路径一起写出来,你可以直接抄作业。
2. 四类高频填空题的识别特征与秒解路径
2.1 日期与日历类:闰年和模七是两个抓手
这类题出现频率极高,典型问法有"某年某月某日是星期几""从某天起再过 N 天是哪一天""某段日期区间内有多少个满足条件的日子"。做题的抓手就两个:闰年规则和星期对7取模。
闰年的判断规则是:能被4整除但不能被100整除,或者能被400整除。写成条件就是(y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)。星期计算可以用基姆拉尔森公式,也可以直接借助工具。我个人最常用的办法是用 Python 的 datetime 模块,一行出结果:
import datetime d = datetime.date(2024, 4, 13) print(d.weekday()) # 0 是周一,6 是周日 print(d.strftime('%A'))如果是问"某天加 N 天",直接用timedelta:
import datetime d = datetime.date(2024, 1, 1) + datetime.timedelta(days=1000) print(d)为什么要用代码而不是手算?因为手算路上有闰年、月份天数、星期起点这几处坑,任何一处错整个答案就废了。代码只错在输入参数上,而参数是你肉眼可见的、能复读确认的东西。这是典型的"用工具的确定性换掉人脑的不确定性"。
2.2 计数与枚举类:三重循环不丢人
"有多少个数满足条件""最多有多少种方案""第 N 个满足条件的数是多少",这类题的通行解法就是暴力枚举。很多选手不敢写多重循环,觉得不优雅。我得说一句:填空题里,本地跑得动的枚举就是最优解。
举个常见形态:求某个范围内各位数字满足特定关系的数的个数。写三层循环枚举每一位,判断条件,计数打印,十行代码解决。哪怕是六位数、七位数的范围,本地跑起来也就几毫秒到几百毫秒。
count = 0 for n in range(1000, 10000): digits = [int(c) for c in str(n)] if sum(digits) == 20 and max(digits) - min(digits) <= 3: count += 1 print(count)这里有个经验点:写枚举代码时,先说清楚"范围边界是否包含",也就是左闭右闭还是左开右闭。蓝桥杯的题干有时候写"1 到 100 之间",这个"之间"是含不含端点,得看题目的语境和你对答案数量级的直觉。如果枚举出来结果很怪(比如刚好比某个整数多1或者少1),回头检查端点。
2.3 数学推导类:能用公式就别写循环
有些填空题,题干里给的数特别大,比如"求 1 到 10 的 9 次方之和""某个大数除以 1000000007 的余数"。这时候循环枚举是跑不完的,必须上公式或快速幂。
常见公式要背:等差数列求和n * (a1 + an) / 2,平方和n*(n+1)*(2n+1)/6,立方和(n*(n+1)/2)^2。组合数可以用阶乘或者杨辉三角递推。快速幂取模的代码模板如下:
def qpow(base, exp, mod): res = 1 base %= mod while exp: if exp & 1: res = res * base % mod base = base * base % mod exp >>= 1 return res print(qpow(2, 1000, 1000000007))推导类题的实操心得是:先在草稿纸上把递推关系写出来,能闭式就闭式,不能闭式再考虑矩阵快速幂或者动态规划。蓝桥杯填空不会把数论推到竞赛数学那么深,但"求和 + 取模"这个组合年年都有。
2.4 大数与精度类:别跟溢出较劲
这类题的识别特征非常明显:阶乘、幂次、非常大的和。比如"100 的阶乘末尾有多少个零""2 的 1000 次方的各位数字之和"。用int或者long long硬算,基本必溢出。
Java 组用BigInteger,Python 组的int本身就是任意精度,C/C++ 组要么手写高精度,要么转成字符串运算。Python 在这类题上优势极大:
n = 100 fact = 1 for i in range(1, n + 1): fact *= i print(fact) print(sum(int(c) for c in str(fact)))Java 的写法:
import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger f = BigInteger.ONE; for (int i = 2; i <= 100; i++) { f = f.multiply(BigInteger.valueOf(i)); } System.out.println(f); int sum = 0; for (char c : f.toString().toCharArray()) { sum += c - '0'; } System.out.println(sum); } }C/C++ 组如果遇到大数,我会建议直接在草稿里换语言:赛前准备好一个能跑的 Python 环境,填空题用 Python 算,编程题用熟悉的语言写。规则没禁止,这就是填空题的便利。
2.5 思维转化类:蚂蚁感冒那种"等效替换"
有一道在圈子里流传很广的题叫蚂蚁感冒,问的是感冒蚂蚁最终会传染多少只。它的关键洞察是:两只蚂蚁相遇后各自掉头,等价于两只蚂蚁直接穿过彼此继续前进,数量上完全一样。这个转化一出来,问题就从"模拟碰撞"变成了"统计位置关系",复杂度瞬间掉下来。
这类题在填空题里也不少。看着像要模拟,其实要转化。判断方法是:如果模拟的状态量太大、步骤太长,就该停下来想"有没有等价简化"。等效替换、对称性、不变量,这三样是思维题的常用武器。练这类题的收益不只是填空,编程题里的省时也会用到。
3. 十秒速解的完整操作流程
3.1 第一步:先读答案要求,再读题干
很多人题都不读完就开始算,这是最容易翻车的习惯。我的固定动作是:先扫一眼题目最后一行,看它要的答案格式。是要一个整数,还是一个字符串,有没有说明"结果是一个几位数"。
这个信息价值极高。如果题目提示"结果是一个三位数",而你算出来五位数,说明模型错了;如果要求填字符串,你要注意大小写和前导零;如果要求精确到小数若干位,你得控制输出格式。先知道交付物长什么样,再决定怎么生产它,这是工程思维。
3.2 第二步:用三个问题决定手算还是写码
我给自己定过一个简单判断表,实测很好用:
| 判断维度 | 倾向手算/心算 | 倾向写代码 |
|---|---|---|
| 搜索空间 | 几十次以内 | 上千次以上 |
| 中间步骤 | 3 步以内 | 需要循环或递推 |
| 出错代价 | 可以反推校验 | 一旦错难定位 |
| 数值范围 | 小整数 | 涉及大数、幂次 |
| 状态变化 | 静态计算 | 有模拟、有过程 |
填表逻辑很简单:只要涉及"大量重复操作"或者"数值超出常规整型",直接写代码;只要三步之内能推出来,手算反而更快,因为省去了开编辑器、写、跑、看结果的时间。中间地带(比如几十次枚举)就看心情,我个人会写代码,因为手算容易在第四五次的时候走神。
3.3 第三步:赛前把这四段模板刻进肌肉记忆
速度的核心是"不需要临时想怎么写"。赛前我会准备好几个片段,闭着眼睛也能敲出来:
- 日期计算(Python datetime 或 Java LocalDate)
- 大数阶乘与各位和(Python 一行循环)
- 暴力枚举(多层 for + 条件判断 + 计数)
- 快速幂取模与组合数
真正比赛时,你只需要改改参数,答案就出来了。这就是"十秒"的现实版本——不是十秒想出算法,而是十秒调出模板。
提示:模板代码要在赛前至少手敲五遍以上,保证不看资料能默写。比赛现场查语法是最浪费时间的行为之一。
3.4 第四步:答案校验三连,别让手滑毁掉一题
算完不代表结束,我坚持做三步校验。第一是数量级校验:跟题目的位数提示对一对,或者用另一种方法估一个量级。第二是边界校验:把范围的小端和大端代进去,看看结果合不合理。第三是末位或奇偶校验:很多计数题的答案有奇偶规律或者末尾数字规律,能反查一部分错误。
举个具体的例子。如果一道题枚举出来是 2023,而你手算一个大致的期望值是 2000 左右,那基本合理;如果你算出来 20230,明显多了一位,就要回头查循环边界。校验花不了二十秒,但能救回一整道题的分。
4. 环境与工具:把 IDE 改造成填空题计算器
4.1 Java 组的速算配置
Java B 组的选手最常遇到的问题是"启动慢、写类烦"。我的做法是赛前在本地 IDE 里建一个空白工程,里面预置好一个Main类,导入常用的java.math.BigInteger、java.time.LocalDate、java.util。比赛时直接改main方法里的逻辑,跑完看控制台。
import java.math.BigInteger; import java.time.LocalDate; public class Main { public static void main(String[] args) { LocalDate d = LocalDate.of(2024, 1, 1).plusDays(1000); System.out.println(d); System.out.println(BigInteger.valueOf(2).pow(100)); } }这里有个细节值得说:Java 的long上限约 9.22×10^18,超过这个范围就得用BigInteger。很多人栽在"以为 long 够用"上。判断方法是,如果你看到题干里出现 10 的 9 次方以上的乘法或者阶乘,直接上BigInteger,不要犹豫。
4.2 Python 组的一行流优势
Python 组做填空是真的爽。日期、大数、组合数、字符串处理,几乎都能一行到几行搞定。itertools里的permutations、combinations能省掉大量手写递归:
from itertools import permutations cnt = 0 for p in permutations(range(1, 10)): if p[0] < p[1] and p[1] > p[2]: cnt += 1 print(cnt)要提醒的是,permutations在元素多的时候会爆内存和爆时间,9 个元素是 36 万种排列,还扛得住;10 个以上就要斟酌。别写出一段跑十分钟的代码,赛场上每一秒都金贵。
4.3 C/C++ 组的溢出防线
C/C++ 组在填空上的最大敌人是溢出和数组越界。我的建议是:枚举计数统一用long long,涉及更大数值时直接转 Python 或者手写高精度。另外,如果一个枚举因为剪枝写复杂了,容易越界,就干脆别剪枝,让循环老老实实跑。
#include <bits/stdc++.h> using namespace std; int main() { long long cnt = 0; for (long long n = 1000; n <= 9999; n++) { int s = 0; long long t = n; while (t) { s += t % 10; t /= 10; } if (s == 20) cnt++; } cout << cnt << endl; return 0; }long long的范围是约 -9.22×10^18 到 9.22×10^18,记住这个数字,能避免很多"明明逻辑对结果却是负数"的谜案。
4.4 单片机与嵌入式方向:客观题是另一套打法
搜蓝桥杯的人里有一大群是单片机和嵌入式方向的,这两类比赛的一阶段或者国赛里会有客观题,题型和算法填空完全不同。它们考的是知识点记忆和概念辨析,比如寄存器配置、中断优先级、定时器模式、通信协议时序、常见电路常识。这类题提不了速,只能靠平时的知识清单。
我自己的复习方式是做一张对照表,把常考模块(GPIO、定时器、串口、AD/DA、中断、看门狗、总线协议)各自的核心配置项、常见陷阱整理成一页纸,考前反复看。这跟算法填空的"模板记忆"是一个道理——把需要临场思考的东西,提前压缩成能直接调用的知识块。
5. 实战踩坑记录与问题速查
5.1 溢出错:最隐蔽也最常见
溢出的可怕之处在于它不报错,只是安静地给你一个错误的数。判断标准很简单:看一眼数字范围。两数相乘超过 21 亿左右就超出int,超过 9.22×10^18 就超出long long。另外取模题要警惕"先算后取模"的顺序,每一步乘法后立刻取模,别等到最后,否则中间结果照样溢出。
5.2 精度错:浮点数不能直接比大小
涉及浮点的填空题,比如求某个面积或者平均值,不要用==比较浮点数,要用误差范围。Python 里可以用Decimal或者控制输出格式。如果题目要求保留几位小数,注意四舍五入的规则,有时候需要+0.0000001再格式化,处理掉二进制表示带来的尾巴误差。
5.3 提交格式错:空格、大小写、前导零
这是最冤的一类失分。填空题要求填一个字符串时,字符串里有没有空格、大写还是小写、是不是固定长度带前导零,都要严格按题目说明来。我吃过一次亏,答案多了一个空格,直接判错。现在的习惯是提交前把答案复制出来,用眼扫一遍首尾,再去点提交。
5.4 常见问题速查表
| 症状 | 可能原因 | 排查动作 |
|---|---|---|
| 结果明显多一位 | 循环边界多算了一轮 | 检查range或for的端点 |
| 结果为负数 | 整型溢出 | 换long long或大数类型 |
| 答案比预期大很多 | 重复计数 | 检查去重逻辑或嵌套顺序 |
| 日期差一天 | 端点包含关系搞错 | 确认"从某天起"是否含当天 |
| 字符串判错 | 大小写/空格/前导零 | 逐字符对照题目要求 |
| 代码跑太久 | 搜索空间过大 | 换数学方法或加剪枝 |
5.5 时间分配:填空别超过总时长的两成
我给自己定的规矩是:填空题总用时不超过整场比赛的百分之十五到二十。两道填空如果十分钟还没头绪,先跳过,去做编程题,最后的空档再回来。原因是填空题的分数性价比虽高,但它的"卡住"往往是无底洞式的,越陷越深。先保住能拿的分,再回来收尾,这个策略帮我救回过好几次比赛。
我个人在实际操作中的体会是,填空题真正练的不是算法水平,而是"路径选择"和"模板储备"。同一道题,有人十分钟推出结果,有人三十秒调出模板跑出答案,差距就在赛前有没有把常见题型沉淀成条件反射。平时刷真题的时候,别只满足于做对,回头想想"这题能不能三十秒解决""我当时为什么绕了远路",把绕路的经验记下来,下一次就是十秒。