Gym101353D ShaatChara (博弈模板)
异或运算符
题意及反省
题意理解错了,导致第三个样例不能理解,
开始以为,假如在我可能胜利的情况下,我要取几次才能够让自己不败,有下面两种情况,
(1)异或值为0,先手必败,以最优的策略,
我自己最少要取一次来改变当前的局面,让自己不败。
(考虑1 1 的情况?必败:按照题意,每个人每一次取,都必须从某一堆石子中取走至少一颗)
(2)异或值为1,先手必胜,我可以不必取。
很混乱了,代码好像逻辑上都讲不通,因为思路的逻辑本来就不对。
后面看了大佬的博客,
题意:
“就是假如第一个人能胜利的情况下,他的第一次取物品,能从哪几堆取,可以继续保持胜利,输出这个堆数。能让他保持胜利的方式是:他取完后,所有物品数的异或值变为0。”
(如果第一个人必败的情况下,直接输出0,因为他不能采取任何行动来取胜
举例:样例2异或值为0,先手必败,输出0)
补充:
He wants to know how many possible moves he may take such that
Meena’s win does not become guaranteed.
他想知道的是,他可能会采取多少可能的行动,而米纳斯的胜利并没有得到保证。
游戏规则:
The game is for two players. Each player takes turn alternatively.
In each turn a player can select any of the piles that has at least 1 stone left, and then remove some stone (at least one) from it.
The game goes on like this until there are no stones left. The player who can’t make a move loses.
ac代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
using namespace std;
const int maxn=10050;
int arr[maxn];
int main()
{
int t,n,cnt=0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int tmp=0,ans=0; // tmp = 0 :0异或任何数=任何数
for(int i=0; i<n;++i)
{
scanf("%d",&arr[i]);
tmp^=arr[i];
}
for(int i=0; i<n; i++)
if(arr[i]>(tmp^arr[i]))
/*
大于号右边的表达式的意思是除了第i堆,其它所有堆的物品数的异或值。
因为 0异或任何数=任何数,前面tmp已经保存了所有堆数的异或值。
举个例子,tmp = a^b^c^d, 所以tmp^a = a^a^b^c^d = b^c^d。
如果第i堆的物品数大于这个异或值,第i堆的物品数就可以减去一个值等于这个异或值,
这样我们就可以得到两个相等的异或值,而 两个相等的数异或值为0,0异或任何数=任何数,
我们就能够保持原来的先手必胜的局面。
*/
ans++;
printf("Case %d: %d\n",++cnt,ans);
}
return 0;
}
混乱的代码
#include <stdio.h>
int
main() {
int t, n, i, k = 0, ans, a[10005];
scanf("%d", &t);
while( t-- ) {
scanf("%d", &n);
for( i = 0; i < n; i++ ) {
scanf("%d", &a[i]);
}
if( n == 1 ) {
printf("Case %d: 1\n", ++k);
}
else {
ans = a[0];
for( i = 1; i < n; i++ ) {
ans ^= a[i];
}
if( ans == 0 ) {
printf("Case %d: 0\n", ++k);
}
else {
printf("Case %d: %d\n", ++k, n);
}
}
}
return 0;
}