1069 微博转发抽奖 (20 分)
题意描述:
小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包。请你编写程序帮助他确定中奖名单。
输入格式:
输入第一行给出三个正整数 M(≤ 1000)、N 和 S,分别是转发的总量、小明决定的中奖间隔、以及第一位中奖者的序号(编号从 1 开始)。随后 M 行,顺序给出转发微博的网友的昵称(不超过 20 个字符、不包含空格回车的非空字符串)。
注意:可能有人转发多次,但不能中奖多次。所以如果处于当前中奖位置的网友已经中过奖,则跳过他顺次取下一位。
输出格式:
按照输入的顺序输出中奖名单,每个昵称占一行。如果没有人中奖,则输出 Keep going…。
输入样例 1:
9 3 2
Imgonnawin!
PickMe
PickMeMeMeee
LookHere
Imgonnawin!
TryAgainAgain
TryAgainAgain
Imgonnawin!
TryAgainAgain
输出样例 1:
PickMe
Imgonnawin!
TryAgainAgain
输入样例2:
2 3 5
Imgonnawin!
PickMe
输出样例 2:
Keep going...
解题思路:
Mara: 转发抽奖我从来都没有中过呢,┐(・o・)┌
Jack: 我最近刚好中了两本书,哈哈哈哈。
Mara: 每隔N个人就发一个红包!中奖间隔是N,这不是很简单吗,就等间隔的去列表中取出元素就好了。
Jack: 还有个注意,可能有人转发多次,但不能中奖多次。所以如果处于当前中奖位置的网友已经中过奖,则跳过他顺次取下一位。真麻烦,直接去重之后再抽奖不就得了。
Mara: 那我能用 for (x = S-1, M, N)
来遍历每个中奖位置吗?然后在检查每个中奖位置是不是已经中过奖,如果是就取下一位。
Jack: 不能!!
Mara: 凭什么,╭(╯^╰)╮
Jack:我已经试过了,这样写有一个测试点通不过。而且这不是题目的本意, ┐(・o・)┌。我看了别人的代码,两个中奖位置之间的距离和N 的关系是 >=
。也就是说,后一个中奖位置至少比前一个中奖位置大N, 后一个中奖位置依赖于前一个中奖位置,只有一个位置中奖了才能叫做中奖位置。
Mara: 我明白你的意思了,循环的次数是不定的,就不该用for
循环,因为步长根本就不清楚。
Jack: 就是就是,做这道题像是回到了高中,咬文嚼字的,还全是歧义。代码写起来一点难度也没有,题意倒是难理解。这种题目除了添堵有什么意思呢?
Mara: 有啊,作为好题目的对照组呀。
Jack: ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄
代码:
def main():
M, N, S = (int(x) for x in input().split())
# 元组拆包,接收三个正整数
data = []
# 存储输入的参与转发的网友们
lucky_dogs = []
# 中奖的那些网友们
for x in range(M):
data.extend([input()])
# 依次读入参与转发的网友名单并存储起来。为什么要用extend ? 因为快,
# 为什么是[input()], 因为extend( ) 只接受列表
index = S - 1
# 列表的下标从0开始,对齐下标而已。其中index指示可能的中奖位置。
while index < M:
# 转发抽奖只对抽奖名单扫描一次
if data[index] not in lucky_dogs:
# 恭喜data[index] 这位网友,肯定中奖了。如果已经中了一次就算了,否
# 则记下ta的网名
lucky_dogs.extend([data[index]])
index += N
# 如果data[index] 中奖了, index就是一个中奖位置,下一个可能的中奖
# 位置至少与这个中奖位置相距N
else:
index += 1
# 根据题意,跳过ta,顺次取下一位
# 最后根据题意输出答案
if len(lucky_dogs) == 0:
print("Keep going...")
else:
for lucky_dog in lucky_dogs:
print(lucky_dog)
if __name__ == '__main__':
main()
易错点:
- 如果处于当前中奖位置的网友已经中奖,则跳过他顺次取下一位。只有在那个位置上有网友中奖了的才是中奖位置。题目中中奖间隔的意思是,任意两个中奖位置之间的最小间隔是N,实际间隔并不确定。
总结: