题意:
有n堆石子,每次可以从一堆石子里面取至少1个石子,或者将一堆石子分为两堆,问先手必赢还是必输
题解:
用SG函数打表找规律,sg[0]=0;sg[1]=1;当有2个石子时,经过操作后可以变成0个,1个,或者(1,1)这三种状态,。。。所有堆的石子个数的sg异或为0则必败。反之必胜。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int MAXN=1e6+5;
int vis[1000];
int sg[1000];
void getsg()
{
sg[0]=0;
sg[1]=1;
for(int i=2;i<=100;i++)
{
memset(vis,0,sizeof vis);
for(int j=1;j<=i;j++)
{
vis[sg[i-j]]=1;
}
for(int j=1;j<=i-1;j++)
{
vis[sg[j]^sg[i-j]]=1;
}
for(int j=0;;j++)
{
if(vis[j]==0)
{
sg[i]=j;
break;
}
}
}
}
int main()
{
/*getsg();
for(int i=1;i<=50;i++)
{
cout<<i<<" "<<sg[i]<<endl;
}*/
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int x;
int ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x%4==0) ans^=(x-1);
else if(x%4==3) ans^=(x+1);
else ans^=x;
}
if(ans==0) printf("Bob\n");
else printf("Alice\n");
}
}