项目标题里出现"多组输入"四个字,很多人第一反应是"不就一个input()吗"。真到在线评测环境里跑起来,情况立刻变得具体:本地手敲两行数据一切正常,提交上去结果一片红;或者干脆卡在读取阶段,程序迟迟不退出;又或者数据量上了十万行,逻辑完全正确却吃了超时。这些问题的根子,九成出在输入层,而不是算法本身。Python3 的输入方式看起来简单,实际上从input()、sys.stdin.readline、sys.stdin.read到sys.stdin.buffer.read,每换一层,性能、行为和边界处理都不一样;而"多组输入"这件事,又分成给组数、读到文件末尾、哨兵值终止三种完全不同的骨架,选错了骨架,后面的代码写得再漂亮也是白搭。下面这些内容,是我把输入这一层单独拎出来反复折腾之后留下的记录,适合刚接触 Python3 输入处理的新手,也适合写过一阵子脚本、结果被多组数据反复折磨的人。
1. input() 到底做了什么:一条字符串背后的三层处理
input()是 Python3 里最常用的输入方式,也是被误解最深的一个。很多人把它当成"从键盘读一个东西进来",这个印象不算错,但在文件重定向、管道传参、在线评测这几种场景下,它读的根本不是键盘,而是标准输入流。理解这一点,后面所有的多组输入写法才有落脚点。
1.1 提示符、缓冲与换行符剥离的顺序
先拆一下内置input()的内部动作。它大致等价于这么一段逻辑:如果传了提示符参数,先把提示符写到标准输出;然后从标准输入读一整行;最后把行尾的换行符去掉,把剩下的字符串返回。注意这个顺序,提示符是写到 stdout 而不是 stderr,意味着你用管道或者重定向跑程序的时候,提示符会混进输出文件里,评测机拿到的结果自然对不上。
所以在任何需要提交到评测环境的代码里,input("请输入:")这种写法是明确的错误示范。提示符在本地看着舒服,在重定向场景下就是纯粹的污染源。我见过不少人本地跑得好好的,一提交就错,排查半天逻辑,最后发现是那行提示文字被当成了输出的一部分。
# 本地调试可以这样,提交前必须删掉提示符 n = int(input("请输入数据组数:"))第二个容易忽略的点是缓冲。input()并不是每调用一次就去操作系统要一次数据,标准输入本身带缓冲,input()只是从这个缓冲区里切一行出来。这带来一个反直觉的结论:input()慢,慢的从来不是系统调用。它是慢在每个数据行都要走一次 Python 层的函数调用、一次文本解码、一次去除换行的字符串操作。数据量小的时候完全无感,上了十万行这个开销就非常可观了。
第三个点是换行符剥离。文本模式下,Python 的 IO 层默认开启通用换行处理,\r\n和\r都会被规范化成\n,所以input()返回的字符串里通常不会残留回车符。但这个"通常"有例外——如果你绕开文本层,直接从二进制缓冲读再自己解码,\r就会原封不动地留在那里,后面做字符串比较的时候莫名其妙不相等。这个坑我在处理 Windows 下导出的数据文件时踩过一次,值得单独记一笔。
1.2 返回值恒为 str,类型转换必须自己动手
input()的返回值永远是字符串,哪怕你敲的是123。这一点新人容易忘,写出来就是这种代码:
a = input() b = input() print(a + b) # 输入 3 和 4,输出 34,不是 7Python 不会帮你隐式转换,"3" + "4"就是字符串拼接。正确做法是在读入的同时就把转换做掉,int(input())或者float(input())。我个人的习惯是读入和转换写成一行,中间不留中间变量,这样转换点唯一,出问题好定位。如果分散在两行,读入一堆再逐个转,中间哪一步漏转了很难看出来。
int()这个转换函数本身也比想象中宽容。它会自动忽略两端的空白,int(" 42 ")得到 42,不会报错;它接受正负号,int("-7")没问题;从 Python 3.6 起它连数字中间的下划线都认,int("1_000")返回 1000。但它不接受小数点,int("3.0")直接抛ValueError,也不接受科学计数法,int("1e3")同样报错。读浮点就必须float(),读完再按需int()截断,别指望一步到位。
提示:
int()转换失败抛的是ValueError,读不到数据抛的是EOFError,这两个异常是两回事。多组输入场景里,靠捕获ValueError来判断输入结束是行不通的,必须靠EOFError或者显式的结束标记。
1.3 空行与纯空白行的真实返回值
空行是个微妙的东西。input()遇到一个空行,返回的是空字符串"",不是None,也不会跳过。如果你写while (s := input()):这种循环,遇到空行就直接退出了,而数据可能还在后面。这一点在"多组数据之间用空行分隔"的格式里是致命的。
纯空白行(只有空格或制表符)更麻烦,input()返回的是" ",非空但内容全无意义。对这类行做int()转换必然抛异常。稳健的处理方式是先strip()再看是否为空,空就continue跳过这一轮,而不是靠捕获异常来兜底。
while True: try: line = input().strip() except EOFError: break if not line: # 空行或纯空白行,跳过 continue # 到这里 line 一定非空这段骨架看起来不起眼,但它同时挡住了空行、空白行和文件结束三种情况,是处理"格式不太规整的多组输入"时最省心的起点。后面所有变体,基本都是在这个骨架上加东西。
2. 一组数据的四种常见形态与对应拆解写法
"一组数据"在题面和实际文件里长得完全不一样。同样是三个整数,可能是三行各一个,可能是一行三个空格隔开,可能是一行三个逗号隔开,还可能是长度不定的一整行。把这四种形态的读法摸熟,多组输入才有拆解的基础,否则每一组都得现场想怎么写。
2.1 单值、同行多值、分行多值、行数不定
先列一张对照表,这四种形态的读法差异一目了然:
| 输入形态 | 典型样子 | 读法 |
|---|---|---|
| 单值 | 一行一个整数 | n = int(input()) |
| 同行多值(定长) | 3 5 7 | a, b, c = map(int, input().split()) |
| 同行多值(变长) | 一行若干个数 | nums = list(map(int, input().split())) |
| 分行多值 | n 行各一个数 | 循环 n 次input() |
| 首行给个数,后续成组 | 首行n,接着 n 行 | 先读 n,再循环 |
第三行和第四行是最容易混的。同行定长的情况可以用解包,a, b, c = ...,写起来短,但有个隐患:如果实际那行多给了一个数字,解包会直接抛ValueError: too many values to unpack。变长的情况必须用list()接住,先拿到列表再按位置取,虽然多写一行,但容错性好得多。我在写一次性脚本的时候贪图方便用解包,结果对方给了个末尾带空格的输入,split()之后多出一个空串,解包失败,白白折腾了十几分钟。
分行多值的关键是循环次数从哪来。如果首行给了 n,就循环 n 次;如果没给,就得靠 EOF 判断或者靠每行的固定结构判断。这两条路的代码长得完全不一样,读题的时候第一件事就是确认有没有"首行一个整数表示行数"这句话。
2.2 map 的惰性陷阱与解包数量不匹配
map()返回的是迭代器,不是列表。这一点在被当成列表用的时候会立刻暴露:
nums = map(int, input().split()) print(nums[0]) # 报错:'map' object is not subscriptable必须包一层list()。但它有个省内存的好处,如果只是遍历一遍求和,完全不需要落地成列表:
total = sum(map(int, input().split())) # 不生成中间列表,直接求和这个写法在处理超长行的时候很实用,一行几十万个数字,list()会实打实占掉一大块内存,sum()直接消费迭代器就没有这个负担。类似地,max、min、any、all都能直接吃迭代器。
解包数量不匹配的问题前面提过一次,这里补一句:a, b = map(int, input().split())在数量不对时抛的是ValueError,而且这个异常和数字格式错误的异常是同一个类型,日志里看不出区别。排查的时候最好先split()出来看一眼实际长度,再决定怎么取。
2.3 用 split() 还是 split(' '):空白语义的差别
split()不带参数和split(' ')带一个空格参数,行为完全不同,这个差别在多组输入的解析里影响很大。
s.split():按任意长度的连续空白分割,包括空格、制表符、换行,并且丢弃所有空串。"a b".split()得到['a', 'b']。s.split(' '):严格按单个空格切,连续空格会产生空串。"a b".split(' ')得到['a', '', 'b']。
绝大多数读入场景应该用不带参数的版本,因为它对"多打了一个空格"这种情况天然免疫。只有一种情况必须用带参数的版本:字段本身可能为空,比如 CSV 里某一列是空值,这时候空串是有意义的,不能被吞掉。
我自己的规则很简单:读数字和普通字符串用split(),读结构化表格用专门的 CSV 模块,不要手搓split(' ')。手搓的结果通常是跑通了一个样本,换个样本立刻崩。
3. 多组输入的终止条件:组数、EOF、哨兵值三分法
多组输入的所有写法,本质上都在回答一个问题:下一组数据还在不在。有三种回答方式,对应三套骨架,选错骨架是最常见的失败原因。下面把三套都摆出来,说清楚各自适用什么题面。
3.1 首行给组数 T 的循环骨架
题面里出现"第一行一个整数 T,表示数据组数"这种描述,就用这个骨架。这是最简单也最不容易出错的一种,因为循环次数是明确的。
t = int(input()) for _ in range(t): n, m = map(int, input().split()) # 处理这一组这段代码看着没毛病,实际有两个隐藏假设:T 之后每一组恰好占一行,以及组内数据不跨行。一旦题面说"每组数据可能占多行",这个骨架立刻失效,得改成按 token 流读取。
还有一个更深的问题:如果 T 和实际数据行数对不上,比如 T 声明 5 组但文件里只有 3 组,程序会在第 4 次input()时抛EOFError直接崩掉。正规题面不会这么出,但自己处理日志文件时会遇到。加个兜底更稳:
t = int(input()) for _ in range(t): try: line = input() except EOFError: break ...3.2 读到文件末尾:while True + EOFError 与 for line in sys.stdin
题面写"输入包含多组数据,处理到文件结束"就属于这一类。Python3 里有两个等价写法。
第一个是while True加异常捕获:
while True: try: line = input() except EOFError: break a, b = map(int, line.split())第二个是直接迭代标准输入:
import sys for line in sys.stdin: a, b = map(int, line.split())第二种写法在 Python2 时代是显式推荐的做法,Python3 里依然好用,而且代码短。需要注意for line in sys.stdin拿到的line带换行符,所以必须strip()或者直接split()(split()会顺带处理掉末尾空白)。如果这行要用字符串比较,忘了 strip 就会永远不相等,这是个高频坑。
两者的性能差别其实不大,因为标准输入本身有缓冲,for迭代在 CPython 里也是走缓冲的。我一般用for line in sys.stdin写脚本,用try/except EOFError写题解,纯粹是习惯问题,功能上等价。
注意:
for line in sys.stdin遇到完全空的文件时循环体一次都不执行,而while True + input()会立刻抛EOFError。空输入场景下这两种写法的行为略有差异,写健壮脚本的时候要留意。
3.3 哨兵终止与"最后一组不输出"的细节
第三种是哨兵值,题面通常写"输入若干组,以 0 0 结束"或者"读到 -1 为止"。这类写法的坑特别集中。
while True: a, b = map(int, input().split()) if a == 0 and b == 0: break print(a + b)逻辑是对的,但有两个细节值得说。第一,哨兵判断必须在处理之前,处理之后判断就会多输出一组。第二,有些题面要求哨兵那组也参与计算(少见但不是没有),这时候判断位置要挪到处理之后。读题时把这句话圈出来,比事后改代码省事得多。
还有一个变体是"以单独一行 0 结束",这行只有一个数字而不是两个。如果用解包写法a, b = map(int, input().split()),读到这一行会直接抛ValueError。正确做法是先把整行读进来判断,或者用列表接住再按长度分支:
while True: parts = list(map(int, input().split())) if len(parts) == 1 and parts[0] == 0: break a, b = parts[0], parts[1]看起来啰嗦,但这种"先接住再判断"的结构对异常格式的容忍度最高,我在处理来源不明的数据文件时基本都用这个套路。
4. 大输入量下的性能塌陷:input() 慢在哪、快读怎么写
数据量小的时候,用哪种读法都无所谓。一旦行数上到十几万,不同读法之间的差距能拉到十倍以上,原本宽松的时间限制也会变得紧张。这一节把性能这件事说透。
4.1 逐行读取与批量读取的开销量级差
先纠正一个流传很广的说法:input()慢是因为每读一行都要做一次系统调用。这个说法是错的。标准输入带缓冲,真正读盘或者读管道的次数远少于调用次数。慢的地方在另外三处:
- 每次调用都要走一遍 Python 函数调用机制,
input()是内置函数,虽然比纯 Python 函数快,但仍然是开销; - 每次调用都要做一次文本解码,把字节转成 str;
- 每次调用都要做一次去除尾部换行的字符串操作。
这三项乘上行数,就是总开销。所以优化思路很明确:减少 Python 层调用次数,把逐行处理改成批量处理。把整个输入一次性读进来,之后全在内存里切片,调用次数从"行数"降到"常数"。
实测的直观感受是:十万行的输入,input()逐行读加split大概要一秒多,改用批量读之后降到零点一秒量级。具体倍数跟机器和 Python 版本有关,但量级差是稳定的。
4.2 sys.stdin.buffer.read().split() 的快读模板
最快的读法是绕开文本层,直接读二进制缓冲:
import sys data = sys.stdin.buffer.read().split() idx = 0 def next_int(): global idx v = int(data[idx]) idx += 1 return v t = next_int() for _ in range(t): a = next_int() b = next_int() print(a + b)这里有个容易被忽略的细节:sys.stdin.buffer.read()返回 bytes,split()之后得到的是 bytes 列表,而int()是直接支持 bytes 的,int(b'123')返回 123,不需要先.decode()。少一次解码,速度快不少。很多人习惯性地先 decode 再 split,白白多花一遍开销。
用指针idx加取值函数的结构,好处是完全解耦于输入的换行位置。数据是一行三个还是折成三行,对这个模板毫无影响,它只认 token 不认行。这正是它适合处理"格式不太规范的多组输入"的原因。
代价是内存。read()会把整个输入读进内存,split()又会生成等量的 bytes 对象列表。输入文件几百 MB 的时候,内存直接爆掉。所以这个模板有个适用边界:输入规模在几十 MB 以内,放心用;上百 MB,得换流式读法。
| 读法 | 适用规模 | 速度 | 内存 |
|---|---|---|---|
input()逐行 | 小数据、逻辑为主 | 慢 | 极低 |
sys.stdin.readline() | 中等 | 中 | 低 |
for line in sys.stdin | 中等,写法短 | 中 | 低 |
sys.stdin.buffer.read().split() | 大数据 | 快 | 高 |
4.3 输出端同样是瓶颈:拼接与 sys.stdout.write
输入优化完了,很多人就收手了,结果还是超时。原因是输出端也是瓶颈,而且更隐蔽。
print()每次调用都会往标准输出写一次,虽然也有缓冲,但每次调用同样有函数调用开销和格式化开销。循环里print十万次,光是这部分就够呛。改进方式有两种:
第一种是收集到列表里,最后一次性输出:
ans = [] for ...: ans.append(str(result)) sys.stdout.write("\n".join(ans) + "\n")第二种是用生成器表达式配合join,连列表都不落地:
sys.stdout.write("\n".join(str(f(x)) for x in data) + "\n")注意末尾那个+ "\n"不能省,join只在元素之间插分隔符,最后一个元素后面没有换行。不加的话某些评测机判格式错误,而且报错信息往往很难看出是少了换行。
print的sep和end参数也有性能影响,print(a, b, sep="\n")比连续两次print快,因为它只调用一次输出。批量输出场景下,这个差别累积起来不小。
提示:交互类问题要注意输出缓冲。有些评测环境要求每次输出之后立刻刷新,否则对方程序等不到你的输出,双方一起卡死。这种情况用
print(..., flush=True)或者手动sys.stdout.flush(),普通题不需要。
5. 格式不稳定时的兼容解析:折行、空行、\r\n 与异常输入
前面讲的都是格式规整的输入。真实场景里,尤其是处理别人给的数据文件、爬下来的文本、导出的日志,格式经常不规整。这一节专门处理这些情况,也是我在实际项目里踩坑最密集的地方。
5.1 一行数据被折成多行时的缓冲区补读
题面说"每组数据一行",实际文件里可能因为编辑器自动换行、导出工具限制行宽之类的原因,被折成了多行。这时候按行读就会错位:第一行读到的数量不够,下一行读到的又是上一组的尾巴。
解决办法是放弃按行,改成按 token 读,也就是前面那个指针模板。它的逻辑是:不管你怎么折行,我按顺序取够我要的数量就停,下一次调用接着往下取。数据折成什么样都无所谓。
如果一定要保持按行读的结构,可以自己维护一个待处理队列:
import sys buf = [] def read_line_tokens(): global buf while not buf: line = sys.stdin.readline() if not line: return None buf = line.split() tok = buf.pop(0) return tok这段代码的意思很直白:缓冲区空了才去读新的一行,读进来切成 token 放进缓冲区,每次取一个。折行、空行、一行多个 token,全都能吃下来。缺点是pop(0)是线性操作,token 多的时候效率不高,可以用collections.deque的popleft()替代,或者干脆用索引下标。
我在做一个日志解析的小工具时用过这个结构,因为日志的行格式本身就不固定,有的记录一行,有的记录因为某个字段太长被拆成两三行。按 token 流处理是唯一能稳住的做法。
5.2 空行过滤与 Windows 换行残留
空行前面提过,这里补充一个具体的过滤写法。不要用if line == ""判断,因为input()已经去掉换行符了," "这种纯空白行判不出来。统一用if not line.strip()。
至于\r\n,前面说过文本模式会规范化,所以input()和sys.stdin拿到的内容一般没有\r残留。真正会出问题的是两种情况。
第一种是自己从二进制层读再 decode:
raw = sys.stdin.buffer.read().decode("utf-8") lines = raw.split("\n") # 注意:Windows 文件里每行末尾会是 "xxx\r"这时候split("\n")之后每个元素末尾都带\r,做字符串比较全不相等。要么改用splitlines()(它会正确处理各种换行符),要么在 decode 之后手动replace("\r\n", "\n")。splitlines()是更干净的做法,它一次处理\n、\r\n、\r三种。
第二种是编码问题。UTF-8 文件带 BOM 的时候,第一个 token 前面会多出三个不可见字节,int()直接报错。这种情况用encoding="utf-8-sig"打开文件,Python 会自动吃掉 BOM。纯文本输入用sys.stdin的话,这个问题一般不会碰到,但如果是自己open()读文件,就得注意。
5.3 前导零、正负号、科学计数法这些边角
最后说几个数值解析的边角情况,都是实际遇到过才想起来的。
前导零:int("007")返回 7,转换本身没问题。但如果这个字段是编号、学号、订单号,前导零是有意义的信息,转成 int 就永久丢了。这种情况必须按字符串读,别转。
正负号:int("-0")返回 0,int("+5")返回 5,都能处理。但如果数字和符号之间夹了空格,int("- 5")会报ValueError。有些导出工具会这么干,得先replace(" ", "")或者用正则提取。
科学计数法:float("1e3")返回 1000.0,int("1e3")报错。要转成整数得两步走,int(float("1e3")),注意大数的时候浮点精度会丢,超过约 15 位有效数字就不准了。大整数场景应该先按字符串处理,或者用decimal.Decimal。
下表是我整理的高频解析异常对照:
| 输入串 | int()结果 | 说明 |
|---|---|---|
" 42 " | 42 | 自动忽略两端空白 |
"007" | 7 | 前导零被去掉 |
"-0" | 0 | 负零归一 |
"1_000" | 1000 | 3.6 起支持下划线 |
"3.0" | 报错 | 必须走float() |
"1e3" | 报错 | 必须走float() |
"" | 报错 | 空串不能转 |
"- 5" | 报错 | 符号和数字间有空格 |
这张表贴在旁边,遇到ValueError的时候先对照一遍,比盲改代码快得多。
6. 把读入层封成模板:本地调试与线上评测的输入差异
写了这么多遍读取逻辑之后,我现在的习惯是把它封装成一个小模块,所有需要大量读入的脚本都复用它。这一节讲讲封装的设计取舍,以及本地调试和线上环境之间的那些差异。
6.1 一个通用 Reader 类的设计取舍
我常用的版本大概长这样:
import sys class Reader: def __init__(self): self.data = sys.stdin.buffer.read().split() self.idx = 0 def int(self): v = int(self.data[self.idx]) self.idx += 1 return v def str(self): v = self.data[self.idx].decode() self.idx += 1 return v def remaining(self): return len(self.data) - self.idx设计上有几个取舍值得说明。第一,初始化时一次性读入全部 token,这意味着它不适合流式处理和超大输入,但换来了极简的调用和极快的速度,多数场景下这个交换是划算的。
第二,int方法直接对 bytes 做转换,不下 decode,这是性能的关键。只有确实需要字符串语义的时候才 decode。
第三,remaining()方法是我后来加的,用途是替代异常来判断输入是否耗尽。有些场景下用异常控制流程写起来别扭,先查一下剩余量再决定要不要继续读,代码可读性好很多。注意这只是个便利方法,不适合用在"边读边判断"的循环条件里,因为它的语义是"还剩几个 token"而不是"下一行还有没有"。
要不要封装成类,取决于项目规模。一次性的小脚本直接写data = sys.stdin.buffer.read().split()就够,没必要上类。但要写好几个脚本、每个都要处理多组输入的时候,有个统一入口能省掉大量重复思考和重复出错。
6.2 本地手敲输入与重定向测试的差别
本地调试的方式会显著影响你对代码正确性的判断,这一点值得单独强调。
手敲输入的时候,你敲完最后一行按回车,然后按Ctrl+D(Windows 下是Ctrl+Z再回车)告诉程序输入结束了。这个操作会触发 EOF,程序正常退出。但很多人不按结束符,直接看着程序"卡住了",以为是死循环,其实是程序还在等输入。这个误会我见过太多次。
更可靠的测试方式是重定向,把样例数据写进文件,用<传进去:
python3 solution.py < sample.txt这样输入有明确的结束点,行为和评测机完全一致。而且可以反复跑,改代码之后一键重测,比手敲快得多。我现在的习惯是每道题都建一个sample.txt,题面给的样例直接粘进去,跑通了再提交。
还有一个差异是输出的行尾。Windows 下用print输出的是\r\n,Linux 下是\n。绝大多数评测机对行尾不敏感,但少数严格的比较会因为这个判错。稳妥的做法是统一用sys.stdout.write加\n,绕开平台差异。
对比一下两种测试方式的差别:
| 维度 | 手敲输入 | 文件重定向 |
|---|---|---|
| 结束点 | 手动按 EOF,容易忘 | 文件读完自动结束 |
| 可重复 | 每次重敲 | 一键重跑 |
| 与实际环境一致性 | 低 | 高 |
| 大数据量测试 | 基本不可行 | 生成文件即可 |
6.3 我踩过的几个坑与排查顺序
最后把几个印象深的坑集中列一下,顺便给一个排查顺序。
第一个坑是strip()用过头。line.strip()会去掉两端所有空白,包括那些本来有意义的空格。有一次处理一个对齐格式的文本,每行前面有固定数量的缩进空格用来表示层级,我顺手 strip 了一下,层级信息全丢,解析结果乱七八糟。正确做法是用rstrip("\n")只去换行,保留其他空白。这个教训是:strip 之前想清楚两端的空白是不是数据的一部分。
第二个坑是split()之后没检查长度就解包。前面提过,a, b = map(int, line.split())在实际数据多给一个字段的时候直接崩。后来我改成一个统一习惯:可变的输入一律parts = line.split()先接住,if len(parts) < 2: continue再取。多写两行,少踩十次坑。
第三个坑是循环变量在异常路径下的状态。while True里读了两个值,第一个读成功第二个抛异常,这一组数据就变成半读状态。如果后面还有兜底逻辑,很容易用着上一轮的残留值继续算。解决办法是把整组的读取放在一个独立函数里,要么整组读完要么整组失败,不给中间状态留机会。
第四个坑是调试输出忘了删。print打到标准错误还好,打到标准输出就直接判错。我现在调试一律用print(..., file=sys.stderr),这样就算忘了删,也不会污染结果,只是多几行日志。
排查顺序我一般是这么走的:先确认程序有没有正常结束(是不是卡在等输入),再看读到的数量对不对(在循环开头打一行计数到 stderr),然后看第一组数据的解析结果(打出来和题面样例对一遍),最后才怀疑算法逻辑。输入层的错误和算法错误表现得很像——都是答案不对——但前者排查成本低得多,先排掉能省大量时间。
说一个我自己反复验证过的结论:多组输入写不对,八成不是语法问题,而是没搞清楚输入到底长什么样。拿到题面或者数据文件的第一件事,应该是把原始内容原样打出来看一遍,看清楚是几行、分隔符是什么、有没有空行、有没有结束标记。这一步花两分钟,能省掉后面半小时的瞎猜。我见过太多人(包括我自己)上来就凭题面的文字描述脑补格式,然后在一堆"看起来对但就是不过"的提交里打转。把输入先看清楚,剩下的都是体力活。