暴力验证函数写好以后,还要把输入转换成列表、整数和字符串,再把答案按题目格式输出。Python 不需要复杂的扫描器;掌握 input、split、map 和解包,已经能处理大多数小数据。
读取一行
input() 读取一行文本,并自动去掉末尾换行:
1from io import StringIO
2
3source = StringIO("5\n")
4n = int(source.readline())
5
6assert n == 5
真实程序中可以直接写:
1# n = int(input())
这里注释掉调用,是为了让代码片段不等待标准输入。int 把字符串转换为整数,float 转换为浮点数。
一行读取多个整数
输入:
13 7 11 15
常见写法是:
1line = "3 7 11 15"
2a = list(map(int, line.split()))
3
4assert a == [3, 7, 11, 15]
执行过程可以拆开理解:
line.split()按任意空白切分,得到字符串列表;map(int, ...)对每个字符串调用int;list(...)保存转换后的全部整数。
如果元素个数固定,可以直接解包:
1line = "10 20"
2left, right = map(int, line.split())
3
4assert left == 10
5assert right == 20
真实竞赛代码通常写成:
1# a = list(map(int, input().split()))
2# x, y = map(int, input().split())
input 与 sys.stdin.buffer
input() 简单清楚,写小数据验证程序时通常足够。如果正式 Python 提交需要读取大量数据,可以使用缓冲输入:
1from io import BytesIO
2
3source = BytesIO(b"4\n1 2 3 4\n")
4readline = source.readline
5
6n = int(readline())
7a = list(map(int, readline().split()))
8
9assert n == 4
10assert a == [1, 2, 3, 4]
真实程序把前两行替换成:
1# import sys
2# readline = sys.stdin.buffer.readline
bytes.split() 同样按空白切分,int(b"123") 也能直接得到整数,所以纯数字输入不必手动解码。
验证代码优先使用容易读懂的 input()。只有输入确实很大时才换成 sys.stdin.buffer,不要让快读模板掩盖验证逻辑。
按 token 读取整份输入
当换行位置不重要时,可以把整份输入按空白切成 token:
1def parse_case(data):
2 tokens = iter(data.split())
3 n = int(next(tokens))
4 a = [int(next(tokens)) for _ in range(n)]
5 target = int(next(tokens))
6 return a, target
7
8
9a, target = parse_case("4\n2 7 11 15\n9\n")
10
11assert a == [2, 7, 11, 15]
12assert target == 9
真实程序可以从 sys.stdin.buffer.read() 获得整份字节数据:
1def parse_all(data):
2 values = list(map(int, data.split()))
3 return values
4
5
6assert parse_all(b"1 2\n3 4\n") == [1, 2, 3, 4]
这种方式很快,但失去了行结构。题目包含整行字符串或空行有特殊含义时,应按行读取。
多组测试数据
常见格式是第一行给出测试组数 t:
1def parse_cases(text):
2 lines = iter(text.strip().splitlines())
3 test_count = int(next(lines))
4 cases = []
5
6 for _ in range(test_count):
7 n = int(next(lines))
8 a = list(map(int, next(lines).split()))
9 assert len(a) == n
10 cases.append(a)
11
12 return cases
13
14
15text = """\
162
173
181 2 3
194
205 5 8 13
21"""
22
23assert parse_cases(text) == [[1, 2, 3], [5, 5, 8, 13]]
把解析写成独立函数有一个好处:可以直接用字符串构造边界用例,不必创建临时输入文件。
输出列表和多行答案
print(*a) 使用 * 解包列表,相当于把元素作为多个参数传给 print:
1from io import StringIO
2
3output = StringIO()
4a = [1, 2, 3]
5
6print(*a, file=output)
7assert output.getvalue() == "1 2 3\n"
sep 控制参数之间的分隔符,end 控制结尾:
1from io import StringIO
2
3output = StringIO()
4
5print(1, 2, 3, sep=",", end="!", file=output)
6assert output.getvalue() == "1,2,3!"
需要积累很多行时,先构造字符串列表,最后一次输出:
1answers = [3, 5, 8]
2text = "\n".join(map(str, answers))
3
4assert text == "3\n5\n8"
常用字符串操作
字符串支持下标和切片,但创建后不能原地修改:
1s = "algorithm"
2
3assert s[0] == "a"
4assert s[-1] == "m"
5assert s[1:4] == "lgo"
6assert s[::-1] == "mhtirogla"
常用判断与变换:
1s = "codeforces-2026"
2
3assert s.startswith("code")
4assert s.endswith("2026")
5assert s.replace("2026", "2027") == "codeforces-2027"
6assert "12345".isdigit()
7assert not "12a45".isdigit()
8assert " Ab C ".strip().lower() == "ab c"
字符串和字符列表之间经常互相转换:
1s = "cba"
2chars = list(s)
3chars.sort()
4result = "".join(chars)
5
6assert result == "abc"
一个完整的验证程序接口
把解析、暴力计算和格式化分开,测试会更简单:
1def two_sum_exists(a, target):
2 for i in range(len(a)):
3 for j in range(i + 1, len(a)):
4 if a[i] + a[j] == target:
5 return True
6 return False
7
8
9def solve(text):
10 tokens = iter(text.split())
11 n = int(next(tokens))
12 a = [int(next(tokens)) for _ in range(n)]
13 target = int(next(tokens))
14 return "YES" if two_sum_exists(a, target) else "NO"
15
16
17assert solve("4\n2 7 11 15\n9\n") == "YES"
18assert solve("3\n1 2 3\n10\n") == "NO"
这种结构比在算法内部反复调用 input 更容易复用,也更容易为边界数据写断言。
比赛时需要根据题面格式快速查找可复制代码,见Python OJ 输入输出速查。更多暴力枚举方法见用 Python 快速编写算法暴力验证程序。