跳转至

PIO8 单组_二维数组

入门通过率 65.93%python3样例通过牛客 AC

牛客原题  源码

讲解章节推导式输入输出处理

一句话

n 行 m 列的整数矩阵,求全部元素之和。

解题思路

这题考什么

输入形态:单组数据,带两个前导数量(行数 n 与列数 m)。 题目虽然把数据排成了矩阵,但要求的只是总和—— 行列结构对答案没有任何影响,所以完全不必真的建一个二维列表。

做法是把整个输入切成 token 流,跳过开头的 n 和 m, 把随后的 n * m 个 token 一口气加起来。 真去建 list of list,要额外创建 n 个列表对象、多一层指针跳转, 对求和这个目标是纯粹的浪费。

为什么切片写成 data[2:2 + n * m] 而不是 data[2:]

两者在本题的合法数据上结果相同。写出上界是让「取多少个数」这件事 直接体现在代码里:读者一眼能看出矩阵一共 n * m 个元素, 而且万一输入末尾多出了无关内容也不会被算进去。

为什么不逐行读

n, m 各自最大 1e3,元素最多 1e6 个,行数最多 1e3 + 1。 行数虽然不算多,但一次 buffer.read() 把 1e6 个数读进来, 比 1e3 次 input() 再各自 split 更直接,也更贴近后面多组题的写法。

数据规模与复杂度

n, m <= 1e3,元素个数最多 1e6,每个元素 <= 1e9, 所以和最大 1e6 * 1e9 = 1e15。这个量级 32 位、乃至有些语言的默认整型都装不下, Python 的 int 任意精度,直接加即可。时间 O(n * m),空间 O(n * m)。

坑在哪

  1. 前两个 token 是 n 和 m,数据从下标 2 开始。切片起点写成 1 会把 m 当成矩阵元素。
  2. 答案只有一个数,print 一次即可,这里没有必要动用 sys.stdout.write—— 那是给成千上万行输出准备的(见 PIO9)。
  3. 和可能达到 1e15,用其他语言复现时必须用 64 位整数。

参考实现

solutions/PIO8.py
1
2
3
4
5
6
import sys

data = sys.stdin.buffer.read().split()
n, m = int(data[0]), int(data[1])         # 前两个 token 是行数与列数,数据从下标 2 开始
# 只求总和,行列结构没有信息量,直接把 n*m 个元素加起来,不建二维列表
print(sum(map(int, data[2:2 + n * m])))
[:octicons-arrow-left-16: PIO7](PIO7.md) [PIO9 :octicons-arrow-right-16:](PIO9.md)