题目来源
题目描述
从0–N-1位置放硬币,每个位置可以放很多硬币,俩人玩,分为先手与后手;
- 所谓先手,就是你先拿,选一个位置随意拿多少个都行
- 所谓后手,就是你后拿,选一个位置随意拿多少个都行
winner是谁?
题目解析
怎么能赢?让对方面临无硬币可拿,也就是想方设法,让arr变成全0数组。
比如:
- 先手面对:1,0,0,先手能赢吗?能:因为他选择1位置,拿走1,变0了
- 先手面对1,1,0,能赢吗?不能,因为他拿了1,就不可能拿走另一个1,所以后手面对的就是010或者100,后手拿走这个1,就后手赢;
观察上面例子:
- 100,三个位置的数,异或和是1 ^ 0 ^ 0=1,即先手赢;
- 110,三个位置的数,异或和是1 ^ 1 ^ 0=0,即先手输;
分析:
- 先手想赢,那你面对arr时,你要看arr的状态,你得有硬币可拿(非全0数组),而且拿完之后,尽量让后手无硬币可拿(全0数组)。
- 对于一个数组,它里面的数都可以表示成二进制
- 而异或操作中:0可以忽视,1和1相消。
- 因此对一个数组中所有数进行异或操作,最终有如下可能:
- 得到一个0
- 得到一个1
- 如果先手遇到了0,那么他必输;否则必赢
void printWinner(std::vector<int> arr){
int eor = 0;
for(int num : arr){
eor ^= num;
}
if(eor == 0){
printf("后手赢");
}else{
printf("先手赢");
}
}