跳到主要内容

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 就是矩阵内容:

累加顺序值累计和
111
223
………
121278

第二组 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 行」的输入节奏。

相关题目​

自测​

加载评论中...