PIO5. 多组 A+B(零尾模式)
题目描述
给定若干组测试数据,最后一组数据为 0 0,作为输入的结尾。
每组数据有两个整数 a 和 b,请你分别求出 a + b。
输入格式
每行有两个整数 a 和 b。
最后一行为 0 0,代表输入结束(这一组不是需要计算的数据)。
输出格式
输出若干行,每行一个整数,代表对应组的 a + b(不含结尾的 0 0)。
示例
示例 1
输入:
1 2
114 514
2024 727
0 0
输出:
3
628
2751
说明:
前三组正常计算;读到 0 0 时立即停止,因此只输出三行。
解题思路
第一步:理解问题本质
和「T 组形式」不同,这里事先不知道有几组数据,而是用一个哨兵值
(0 0)表示结束。这类题必须用循环,每读一组就判断一次:
「这一组是不是结束标记?」是就 break,否则才计算输出。
第二步:把哨兵当成普通数据会怎样
如果只写 for 循环而不知道次数,就要么漏读、要么把 0 0 也算成一组
(输出一个多余的 0)。所以关键是先把这一对读出来,再判断,
判断通过才计算。
第三步:一次性读入的写法
同样可以先把整段输入读成 token 列表,再用 i 两两推进:
while i + 1 < len(data):
a, b = int(data[i]), int(data[i + 1])
i += 2
if a == 0 and b == 0:
break
...
注意循环条件是 i + 1 < len(data) —— 保证还能凑出一对数。
另外判断必须是 a == 0 and b == 0,不能只看其中一个:
题目只约定「两个都为 0 才是结尾」,单独的 0 5 仍然是合法数据。
完整代码实现
算法可视化 · 逐帧回放这道题的代码29 帧 · 录制输入
import sys
def solve() -> None:
"""读到 0 0 为止,逐行输出 a + b"""
data = sys.stdin.read().split()
out = []
i = 0
while i + 1 < len(data):
a = int(data[i])
b = int(data[i + 1])
i += 2
if a == 0 and b == 0: # 结束标记
break
out.append(str(a + b))
sys.stdout.write("\n".join(out) + "\n")
if __name__ == "__main__":
solve()
示例推演
输入 token 序列为 1 2 114 514 2024 727 0 0:
| 轮次 | 读到的 a, b | 是否结束 | 输出 |
|---|---|---|---|
| 1 | 1, 2 | 否 | 3 |
| 2 | 114, 514 | 否 | 628 |
| 3 | 2024, 727 | 否 | 2751 |
| 4 | 0, 0 | 是 → break | — |
最终输出三行。
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 逐行读 + break | O(T) | O(1) | 直观 |
| 一次性读入 | O(总字符数) | O(总字符数) | 推荐,I/O 更省 |
T 为实际需要计算的数据组数。
易错点总结
1. 把 0 0 也输出了
这是最常见的错误:先输出再判断。一定要先判断是否结束, 通过后才计算。
2. 只判断一个 0
a == 0 或 b == 0 都不够 —— 0 5 是合法数据,答案是 5。
必须是 a == 0 and b == 0。
3. 循环条件越界
用下标推进时,循环条件要写成 i + 1 < len(data);
若写成 i < len(data),最后一轮可能访问不到 data[i + 1]。
扩展思考
- 如果结束标记改成单独一行
0(只给一个数),循环就要改成一元判断。 - 「T 组形式」「零尾模式」「读到 EOF」是三种主流输入约定, 读输入的骨架不同,但处理单组数据的逻辑可以完全复用。