题目截图
![在这里插入图片描述](https://img.php1.cn/3cd4a/1eebe/cd5/7d7ef3f69d479716.webp)
题目摘要
Alice和Bob轮流在数组a中不放回地选数字,Alice先选
如果Alice最终选的数字的总和是偶数,那么Alice获胜
否则,Bob获胜
题目分析
- 我们只需要考虑奇数和偶数出现的次数即可,设偶数出现a次,奇数出现b次,不妨设偶数为0,奇数为1
- 一种简单的想法是,如果a % 2 = 0, 且b % 4 = 2, 那么bob总是能做alice的跟屁虫,和alice平分,最终alice获得b / 2个奇数,也就是2m + 1个奇数,和就是奇数,所以bob获胜
根据上述的分类,我们可以参照mod 4这个标准,进行分析
- b % 4 = 2,bob要做alice的跟屁虫(alice选啥bob就选啥),如果alice选了最后一个0,没办法bob只能继续选1,但这不影响bob和alice最终平分1,也就是2m + 1个奇数,alice的和是奇数,bob胜
- b % 4 = 3,参照上述情况,alice先选一个1使得b % 4 = 2,这样的话,bob就成了b % 4 = 2先选的,所以alice一定可以获得奇数个1,加上之前的第一个1,所以和就是偶数,alice胜
- b % 4 = 0,alice先选一个0,之后alice做bob的跟屁虫,如果bob选了最后一个0,没办法alice只能继续选1,但这不影响bob和alice最终平分1,也就是2m个奇数,alice的和是奇数,alice胜
- b % 4 = 1,如果alice和bob先选了1,就会转化为b % 4 = 0的情况,所以第一个选1的人后面将会选到偶数个1
- 如果a % 2 = 1,bob会选到第一个1,那它接着会选到偶数个1,意味着bob选到的和是奇数,alice选到的和是偶数,alice胜
- 如果a % 2 = 1,alice会选到第一个1,那它接着会选到偶数个1,意味着alice选到的和是奇数,bob胜
ac code
import sysinput = sys.stdin.readline
def debug(func):def wrapper(*args, **kwargs):print('----------------')res = func(*args, **kwargs)print('----------------')return resreturn wrapper
from types import GeneratorTypedef bootstrap(f, stack=[]):def wrappedfunc(*args, **kwargs):if stack:return f(*args, **kwargs)else:to = f(*args, **kwargs)while True:if type(to) is GeneratorType:stack.append(to)to = next(to)else:stack.pop()if not stack:breakto = stack[-1].send(to)return toreturn wrappedfuncdef solve():n = int(input().strip())a = list(map(int, input().split()))odd, even = 0, 0for aa in a:if aa % 2 == 0:even += 1else:odd += 1if odd % 4 == 2:print('Bob')elif odd % 4 == 3:print('Alice')elif odd % 4 == 0:print('Alice')else:if even % 2 == 1:print('Alice')else:print('Bob')if __name__ == '__main__':for _ in range(int(input())):solve()
总结
在dp面前,数学就是降维打击~