真题建议 60 分钟学习等级 8/8

PYTHON LESSON 126

真题精讲:射箭计分与最短路计数

吃透两道八级真题风格编程题:距离比较用平方避免浮点误差,复合题拆成“模板 + 小扩展”。

00 · 学习目标

这一课要解决什么?

先想一想真题里的几何题,其实一个根号都不用开,你信吗?
完成任务真题解剖实验室
学习顺序去掉故事外衣 → 识别模型 → 写正确基线 → 检查边界

学完后,你应该能够

  • d2 = (x - a) ** 2 + (y - b) ** 2 与 r * r 比较
  • d2 == r2 判压线、d2 < r2 判圆内
  • dist 与 cnt 双数组同步推进

01 · 核心概念

几何判定的平方比较法 + 最短路计数复合题

几何判定的平方比较法 + 最短路计数复合题:圆心 (a, b)、半径 r,每支箭一个落点:圆内 10 分、压线 5 分、圆外 0 分。剥掉射箭的故事外壳,本质就是“点与圆的位置关系”判定——读题时把故事翻译成数学对象,是真题第一道关卡。

考级对应GESP Python 8 级 · 代数与平面几何计算GESP Python 8 级 · 单源最短路(Dijkstra)
学习边界

有向无环图、拓扑排序、强连通分量和负权最短路是图论后续主题。

02 · 语法与规则

先记住这 3 条,再开始写程序

01d2 = (x - a) ** 2 + (y - b) ** 2 与 r * r 比较

先准确读出这条写法的结构与作用。

02d2 == r2 判压线、d2 < r2 判圆内

换一组最小数据,手工推演一次结果。

03dist 与 cnt 双数组同步推进

再用边界值或反例确认它的适用条件。

03 · 完整实例

代码、运行结果和解释放在一起看

g8-real-exam-breakdown.pyPYTHON 3.12
# 真题精讲:两道八级真题风格编程题一次讲透

# —— 题 1:射箭计分(几何判定,对应题库 py-exam-l8-a1)——
def archery(a, b, r, points):
    total = 0
    r2 = r * r
    for x, y in points:
        d2 = (x - a) ** 2 + (y - b) ** 2   # 关键技巧:比较距离的平方,不开根号
        if d2 < r2:
            total += 10                    # 圆内(不含边界)10 分
        elif d2 == r2:
            total += 5                     # 恰好压线 5 分
    return total

# 样例:圆心 (0, 0),半径 5,共 5 支箭
pts = [(3, 4), (5, 0), (6, 0), (0, 0), (-3, -4)]
print("射箭总得分:", archery(0, 0, 5, pts))   # 5+5+0+10+5

# —— 题 2:最短上学路线有几条(Dijkstra + 计数,对应题库 py-exam-l8-a2)——
import heapq

def count_shortest(n, edges, start, end):
    MOD = 10**9 + 7
    graph = [[] for _ in range(n + 1)]
    for u, v, w in edges:
        graph[u].append((v, w))
        graph[v].append((u, w))
    INF = float("inf")
    dist = [INF] * (n + 1)
    cnt = [0] * (n + 1)
    dist[start] = 0
    cnt[start] = 1
    heap = [(0, start)]
    while heap:
        d, u = heapq.heappop(heap)
        if d > dist[u]:
            continue
        for v, w in graph[u]:
            nd = d + w
            if nd < dist[v]:               # 更短:距离与方案数一起更新
                dist[v] = nd
                cnt[v] = cnt[u]
                heapq.heappush(heap, (nd, v))
            elif nd == dist[v]:            # 一样短:方案数累加并取模
                cnt[v] = (cnt[v] + cnt[u]) % MOD
    return dist[end], cnt[end]

# 样例:4 个路口、4 条双向路,1→2→4 与 1→3→4 并列最短
edges = [(1, 2, 2), (1, 3, 2), (2, 4, 3), (3, 4, 3)]
d, c = count_shortest(4, edges, 1, 4)
print("最短路程:", d, "路线条数:", c)
运行结果OUTPUT
射箭总得分: 25
最短路程: 5 路线条数: 2

题 1 五支箭分别得 5、5、0、10、5 分;题 2 的 1→2→4 与 1→3→4 并列最短(长度都是 5),所以是 2 条。

在新标签运行和修改这个实例已装入本课代码 · 可自定义输入 · 可提交判题

04 · 逐步理解

每一步只解决一个问题

  1. 01

    题 1 读题:翻译成几何判定

    圆心 (a, b)、半径 r,每支箭一个落点:圆内 10 分、压线 5 分、圆外 0 分。剥掉射箭的故事外壳,本质就是“点与圆的位置关系”判定——读题时把故事翻译成数学对象,是真题第一道关卡。

    PYTHON
    # 位置关系:d 与 r 比大小
    # d < r 圆内 / d = r 压线 / d > r 圆外
  2. 02

    题 1 关键技巧:比平方,不开方

    算真实距离要开根号,浮点误差随之而来——而压线判断偏偏是“相等”比较,最怕误差。技巧:全程比较距离的平方 d2 与 r²,整数运算零误差,还省了一次 sqrt。几何题看到距离比较,先想平方。

    PYTHON
    d2 = (x - a) ** 2 + (y - b) ** 2
    if d2 < r2: ...
    elif d2 == r2: ...
  3. 03

    题 1 边界:< 与 == 别写反

    “圆内(不含边界)”用严格小于,“恰好压线”用等于——两个分支写反,样例可能照样过,大数据直接翻车。考试把“含不含边界”圈出来,再写分支。

  4. 04

    题 2 读题:复合题 = 模板 + 扩展

    “最短路程 + 最短路线有几条”就是 122 课的复合题型:Dijkstra 骨架一行不动,只多带一个 cnt 数组。真题的“难题”很多是老模板穿新衣服,认出骨架就赢了一半。

    PYTHON
    dist[start] = 0
    cnt[start] = 1
  5. 05

    题 2 编码与数据范围

    更短就 dist、cnt 一起更新,等长就 cnt 累加取模。注意范围:10^5 个点、2×10^5 条边,邻接表加堆优化是必须,邻接矩阵光内存就要 10^10 个格子,直接爆。读题先估算,老规矩。

    PYTHON
    elif nd == dist[v]:
        cnt[v] = (cnt[v] + cnt[u]) % MOD
  6. 06

    真题四步套路总结

    一建模:把故事翻译成图或几何对象;二套模板:Dijkstra、平方比较这些老朋友直接写;三查边界:压线、起点、取模、编号从 0 还是从 1;四对样例:手算一遍再对程序输出。四步走完,提交才有底气。

05 · 练习与检验

自己写出来,才算真正学会

本课实作步骤
  1. 1运行实验室,核对得分 25、路线 2 条
  2. 2手算 (3, 4) 到圆心的距离平方是 25
  3. 3把半径改成 3,预测得分怎么变
  4. 4总结“模板 + 扩展”的复合题套路
打开本课编程实验室编辑、运行、测试、判题都在一个页面完成

06 · 完整知识

继续理解定义、规则和适用边界

第一次学习先完成上面的六个步骤;需要查定义、核对规则、分析误区或理解“为什么”时,再展开对应知识章。

核心数据结构树、图、DFS、BFS 与最短路从节点与边的模型出发,掌握遍历、连通性、树结构、最小生成树和最短路径的适用条件。

正式定义

图由顶点和边构成;树是连通且无环的无向图。DFS 沿路径深入后回溯,BFS 按距离层次扩展。算法的正确选择取决于图是否有向、边权是否为负、是否稠密以及目标是遍历、连通还是最短路。

必须掌握

  • 邻接矩阵占 O(V²) 空间,适合稠密图和快速查边;邻接表占 O(V+E),适合稀疏图。
  • DFS 常用递归或显式栈,BFS 使用队列;一般图都必须记录 visited 防止重复和死循环。
  • 无权图的 BFS 首次到达即得到最少边数距离,可用 parent 还原路径。
  • 树有 V-1 条边且任意两点路径唯一;二叉树前/中/后序描述根的访问时机。
  • Dijkstra 只适用于非负边权;Floyd 求所有点对最短路并允许负边,但不能有可达负环。
  • Kruskal 按边权排序并用并查集避环,得到连通无向带权图的最小生成树。

常见误区

  • 遍历一般图时不记录 visited
  • 对负权边使用 Dijkstra
  • 混淆最短路径树与最小生成树
  • 递归 DFS 忽略深度限制

适用边界

  • 有向无环图、拓扑排序、强连通分量和负权最短路是图论后续主题。
  • 网格搜索也是图搜索:格子是顶点,可移动关系是边;不要只背二维数组模板。
打开本章完整示例与独立阅读页 →
Python 基础运算符、表达式与优先级完整区分算术、比较、逻辑、成员、身份和位运算,并用优先级表消除歧义。

正式定义

表达式求值得到一个值。运算符规定如何组合操作数;当一个表达式含多个运算符时,优先级和结合方向决定求值顺序,括号可以明确改变顺序。

必须掌握

  • / 总是得到浮点结果;// 是向负无穷方向取整的整除;% 与 // 满足 a == (a // b) * b + a % b。
  • 比较可以链式书写,如 0 <= x < 10;and/or 会短路并返回最后求值的操作数,不一定返回 bool。
  • == 比较值是否相等,is 比较是否为同一个对象;判断 None 应写 is None。
  • in/not in 做成员测试;对 dict 测试的是键。
  • 位运算作用于整数的二进制位;负整数按无限长二进制补码语义理解。
  • 复杂表达式即使能靠优先级正确运行,也应使用括号表达意图。

常见误区

  • 把 // 当成简单截断
  • 用 is 比较数字或字符串的值
  • 忘记 and 的优先级高于 or
  • 连续位移、比较和逻辑运算却不加括号

适用边界

  • 浮点数比较受二进制表示误差影响,需要按问题选择容差。
  • 运算符可由自定义类重载,因此相同符号对不同类型可能有不同语义。
打开本章完整示例与独立阅读页 →
数学基础计数原理、组合数与计算几何基础明确有序/无序、互斥/分步与几何退化边界,再把公式转为稳定程序。

正式定义

加法原理用于互斥方案分类求和,乘法原理用于依次完成步骤求积;排列关心顺序,组合不关心顺序。计算几何用坐标、向量、距离和方向关系把图形条件转成数值判定。

必须掌握

  • A(n,m)=n!/(n-m)!,C(n,m)=n!/(m!(n-m)!),并有 C(n,m)=C(n,n-m)。
  • 杨辉三角递推 C(n,m)=C(n-1,m-1)+C(n-1,m),边界 C(n,0)=C(n,n)=1。
  • 取模下的组合数算法取决于 n、模数是否为质数、查询次数和是否允许预处理。
  • 距离比较应优先比较平方,避免不必要的 sqrt 和浮点误差。
  • 三角形必须满足任意两边之和大于第三边;共线、重合、零长度是几何边界。
  • 浮点比较应按题目误差使用容差;整数坐标能用叉积时优先保持整数计算。

常见误区

  • 未判断顺序是否重要就套排列组合公式
  • 模意义下直接做普通除法
  • 浮点数直接用 ==
  • 漏掉共线或退化图形

适用边界

  • 概率需要在计数结果上再建立样本空间,不等同于组合数本身。
  • 复杂计算几何涉及方向、相交、凸包等更多主题,本章只覆盖课程实际使用的基础判定。
打开本章完整示例与独立阅读页 →
算法方法算法、复杂度与解题验证把题意转成输入、状态、规则与输出,用正确性和复杂度共同评价解法。

正式定义

算法是解决一类问题的有限、明确步骤。正确性说明算法对所有满足前置条件的输入都得到规定结果;时间和空间复杂度描述输入规模增长时资源使用的增长量级。

必须掌握

  • 先明确输入规模 n、数据范围、目标和允许误差,再选择数据结构与算法。
  • O(1)、O(log n)、O(n)、O(n log n)、O(n²)、O(2ⁿ) 表示增长量级,不是精确运行秒数。
  • 顺序代码复杂度取较大项,嵌套循环常相乘,二分每步把范围缩小一半。
  • 正确性可用循环不变量、数学归纳、交换论证、反证或状态定义来说明。
  • 样例只验证少量输入;必须自己设计边界、极端、重复、有序/逆序和无解数据。
  • 优化前先得到正确基线并测量瓶颈,不为小数据盲目增加复杂实现。

常见误区

  • 只看样例通过就宣称正确
  • 不看数据范围使用 O(n²)
  • 二分区间开闭混用
  • 把 O(n) 当成永远比 O(log n) 慢固定倍数

适用边界

  • 复杂度隐藏常数与硬件差异,但仍是比较规模增长的核心工具。
  • 考场策略、课程完成度和算法能力是不同证据,任何单项都不能保证考级通过。
打开本章完整示例与独立阅读页 →

完成检查

确认自己会解释、会编写、会验证