赞
踩
异或:两个数相同为0 不同为1 例如 1xor1=0 0xor0=0 0xor1=1 1xor0=1
即0碰到任何数都不改变,1碰到1会为0、碰到0不变
思路:
把取的数看成二进制数,从最大位到最小位进行考虑
下面一位位进行分析:
1.分析可知,如果在这一位上面 有偶数个1,则不管怎么样都是平局,因为a取了1之后b总有办法让其变平,而a无可奈何。此时a,b取1个数一定相等(同为奇或同为偶),则一定平局。
2.如果这个位上面 只有1个1,则先手胜
3.如果这个位上面 有奇数个1:
基于:一个奇数只能拆分成两个奇偶性不同的非负整数,当前这一位一定能分出胜负。
则问题转换为,谁获得最后一个1,谁取得胜利(前面拿到的1总会互相抵消)。此时0的作用就是相当于让自己轮空,即先后手交换。将0和1想象为一个序列。
(1)如果是偶数个0的话,相当于互相抵消,a和b都无法通过0来让自己轮空(对方取了0之后,先后手交换,你必须也取0来抵消对方取0造成的影响),则此时先手胜。
(2)如果是奇数个0的话,后手能通过0来使得自己轮空,且先手抵消不了这种影响。总能成功改变先后手顺序。
例如111 0 这个序列 a取0 b变成先手,a取1 b取0 a只能继续取1 此时b变成先手。 111000也是类似的,a取0b取0 ,若a继续取0,则b先手,若a取1,则转换为上面分析的情况。a取1,则b通过0来交换先后手顺序,且由于0还有两个,a逆转不了这种影响。可知在奇数0情况下,后手无论如何都能改变先后手顺序,获得胜利。
1.获得每一位的1数量num,0的数量就是n-num
- def Get_Bit(k):
- global arr
- n=0
- while(k>=1):#按位与运算,求得每一位的1数量
- arr[n]+=k&1
- k>>=1
- n+=1
2. 对所有数进行异或运算,若最终为0。由异或的性质(结合律,交换律)可知:
将所有数任意划分为两个非空集合,这两个集合中的异或和相等,ab初始值为0,那么最终异或的结果肯定也是相等的。
- for i in range(1,len(rnt)):
- Get_Bit((rnt[i]))
- flag^=rnt[i]
- if flag==0:
- print(0)
- continue
全部代码如下:
- n=int(input())
-
- def Get_Bit(k):
- global arr
- n=0
- while(k>=1):#按位与运算,求得每一位的1数量
- arr[n]+=k&1
- k>>=1
- n+=1
-
- for i in range(n):
- arr=[0 for i in range(22)]
- rnt=list(map(int,input().split()))
- flag=0
- for i in range(1,len(rnt)):
- Get_Bit((rnt[i]))
- flag^=rnt[i]
- if flag==0:
- print(0)
- continue
- for i in range(21,-1,-1):#三种情况,其实只需要把整个1和0给想象成一个数列,a和b都是想获得最后胜利,即为了最后一次获得1(通过0来改变运算顺序),如果0为偶数,1为奇数,则无论如何b都变不了,a胜,反正亦然
- if arr[i]%2 == 0:
- continue
- elif (arr[i]%2 and (len(rnt)-1-arr[i]) %2 ==0 ) or arr[i]==1 :
- print(1)
- break
- else:
- print(-1)
- break
图源:试题 历届真题 异或数列【第十二届】【省赛】【A组】-CSDN博客
对于输入较大的可加入:加速读取
input=sys.stdin.readline
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。