问题描述
试题编号: 201912-1
试题名称: 报数
时间限制: 1.0s
内存限制: 512.0MB
问题描述:
解题思路
- 用列表by_count_list来存储四人各自跳过的次数。下标0, 1, 2, 3分别对应甲乙丙丁。
- 每报一个数(无论跳过与否),下一次报数轮到后面一个人。具体实现如下:用bucket变量来记录下一次报数轮到的人。初值是0。每报一次,就令bucket = (bucket + 1) % 4。
- 用next_number变量来记录下一次要报的数。用report_count变量来记录没有跳过的数字的总数。初值为0。
- 报下一个数时,无非两种情形,要么跳过要么不跳过。跳过的话,by_count_list[bucket]加1;没有跳过的话,report_count加1。
- 题解的核心步骤是:
当report_count < n:
求出下一个要报的数,即next_number += 1;
跳过的话,by_count_list[bucket]加1;没有跳过的话,report_count加1;
算出下一个要报数的人,即令bucket = (bucket + 1) % 4。
参考答案
n = int(input())
bucket = 0 #0, 1, 2, 3号桶分别对应甲乙丙丁
by_count_list = [0] * 4 #甲乙丙丁跳过数字的次数
next_number = 0 #接下来要报哪一个数(无论是否跳过)
report_count = 0 #没有跳过的数字的总数
while report_count < n:
next_number += 1 #接下来报的数
if next_number % 7 == 0 or '7' in str(next_number):
by_count_list[bucket] += 1
#print("next_number=", next_number, "[", bucket, "] += 1")
else:
report_count += 1
#print("-->", next_number, "[", bucket, "]:", by_count_list[bucket])
bucket = (bucket + 1) % 4 #下一轮报数的人
for i in range(4):
print(by_count_list[i])
测试用例
题目描述给出的两组测试用例是常规情形。摘录如下,供复制。
- n的取值为常规情形。(见题目描述的样例1)
样例输入
20
样例输出
2
1
1
0 - n的取值为常规情形。(见题目描述的样例2)
样例输入
66
样例输出
7
5
11
5 - n=1, 边界情形。
样例输入
1
样例输出
0
0
0
0 - n=80,考察连续跳过的情形。连续跳过10次。
样例输入
80
样例输出
呃…
手工构造样例输出吃力不讨好。
怎么办?
答:输出中间结果。做法就是加入第11行的代码,即
print("next_number=", next_number, "[", bucket, "] += 1")
这行代码可以帮我们看到跳过了哪些数字。中间结果输出摘录如下:
next_number= 7 [ 2 ] += 1 //第3人,即丁跳过次数加1
next_number= 14 [ 1 ] += 1
... //此处省略多行
next_number= 67 [ 2 ] += 1
next_number= 70 [ 1 ] += 1
next_number= 71 [ 2 ] += 1
next_number= 72 [ 3 ] += 1
next_number= 73 [ 0 ] += 1
next_number= 74 [ 1 ] += 1
next_number= 75 [ 2 ] += 1
next_number= 76 [ 3 ] += 1
next_number= 77 [ 0 ] += 1
next_number= 78 [ 1 ] += 1
next_number= 79 [ 2 ] += 1
next_number= 84 [ 3 ] += 1
... //此处省略多行
next_number= 112 [ 3 ] += 1
据以上输出,连续跳过数字的情形下程序是正确的。
如果要跟踪更多信息,启用第14行代码。
小结
- 题解算法步骤与报数过程存在清晰的映射关系。上述程序代码正是用计算机语言实现了报数过程。
- 在代码中插入输出中间结果的语句,可以用来调试程序,也可以用来判断程序的正确性。要注意的是,一定要注释掉这类代码,再提交。提交前,要再次运行程序,确保运行输出与题目描述中的样例输出一致。