PIO9. 多组 二维数组求和(T 组形式)
题目描述
给定 T 组询问,每次询问给出一个 n 行 m 列的二维正整数数组 A, 其中第 i 行第 j 列元素的值为 A[i][j]。请你分别求出每个数组所有元素之和。
输入格式
第一行一个整数 T。 随后 T 组数据。每组的第一行有两个整数 n 和 m。 每组的随后 n 行,每行有 m 个整数 A[i][j]。
输出格式
输出 T 行,每行一个整数,代表对应数组的元素之和。
示例
示例 1
输入:
3
3 4
1 2 3 4
5 6 7 8
9 10 11 12
1 1
2024
3 2
1 1
4 5
1 4
输出:
78
2024
16
说明: 第一组 3×4 数组所有元素之和为 1+2+…+12 = 78; 第二组只有一个元素 2024;第三组 1+1+4+5+1+4 = 16。
解题思路
第一步:理解问题本质
这是「T 组」结构的升级版:每一组内部又有自己的结构(先 n、m,再一个 n×m 的矩阵)。但只要记住「先读元数据,再读数据」的节奏,就不会乱。
第二步:真正构造二维数组
最直观的写法是把矩阵真的存进二维列表:
grid = [[int(input()) for _ in range(m)] for _ in range(n)]
它能工作,但完全没必要 —— 题目只要求求和,存下来纯属浪费内存。
第三步:摊平后累加(推荐)
把所有 token 一次性读进来后,一个 n×m 的矩阵在 token 序列里就是
连续的 n*m 个数。于是直接连续读 n * m 个数字累加即可:
total = 0
for _ in range(n * m):
total += int(data[idx])
idx += 1
不需要下标 i、j,也不需要二维列表,代码更短、更快。
完整代码实现
算法可视化 · 逐帧回放这道题的代码87 帧 · 录制输入
import sys
def solve() -> None:
"""读取 T 个二维数组,逐行输出各自的元素之和"""
data = sys.stdin.read().split()
if not data:
return
idx = 0
t = int(data[idx])
idx += 1
out = []
for _ in range(t):
n = int(data[idx])
m = int(data[idx + 1])
idx += 2
total = 0
for _ in range(n * m): # 二维数组摊平后逐个累加
total += int(data[idx])
idx += 1
out.append(str(total))
sys.stdout.write("\n".join(out) + "\n")
if __name__ == "__main__":
solve()
示例推演
以第一组(3×4 矩阵)为例,读入 n=3、m=4 后, 接下来的 12 个 token 就是矩阵内容:
| 累加顺序 | 值 | 累计和 |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 2 | 3 |
| … | … | … |
| 12 | 12 | 78 |
第二组 n=1、m=1,累加 1 个数得到 2024。 第三组 n=3、m=2,累加 6 个数得到 16。
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 构造二维数组 | O(Σ n*m) | O(Σ n*m) | 直观但浪费空间 |
| 摊平累加 | O(Σ n*m) | O(总输入 token) | 推荐 |
Σ n*m 为所有数组元素总数。
易错点总结
1. 把 n、m 读反
矩阵是 n 行 m 列,读的时候按 n 再 m 的顺序;
虽然求和时 n*m 与顺序无关,但为了可读性要写对。
2. 误以为每组都是同样大小
每组数据都重新给出自己的 n、m,大小可以完全不同, 不能复用一个全局的 n、m。
3. 逐行读时忽略了空行
如果题目数据里混有空行,用 readline 逐行读需要额外跳过空行;
一次性 read().split() 会自动忽略所有空白,更省心。
扩展思考
- 如果要求的是每行之和而不是总和,就需要找回行边界: 每读 m 个数就是一行。
- 二维前缀和、矩阵旋转等题目同样遵循「先读 n、m,再读 n 行」的输入节奏。