Time Limit: 1.0 Seconds Memory Limit: 65536K
Total Runs: 144 Accepted Runs: 30
Alice and Bob are playing a game. There is a line chess(black and white) in front of them. Firstly, one of them choose two continuous black chess, and replace them to a white chess. And then, next people do the same thing. The one who can not do anything is the loser. Alice is the first one. Now, could you tell me who will be the winner.
Input
The input consists of multiple test cases. The first line contains an integer
T
, indicating the number of test cases.
(1≤T≤1000)
Each case contains one integer
N
.
(1≤N≤1000)
. Then comes a sequence of length N with 0 or 1, 1 means black chess and 0 means white chess.
Output
For each case, if Alice wins, output"Alice", otherwise output"Bob".
Sample Input
2
6
011110
1
1
Sample Output
Alice
Bob
【分析】
暴力求SG函数,所有连续的黑点看成一组单独的游戏,所有游戏的答案异或一下就是最终答案.
这里当前可改变的状态就是枚举取当前段中的任意相邻两个合并成一个白色点,合并后必然会使得当前连续的黑点变成两段连续的黑点,那么后继状态就是(sg[i-j-2]^sg[j])
关于SG函数:博弈入门—NIM&SG
【代码】
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int sg[1100]={0};
int vis[1100];
char s[2000];
void init()
{
sg[0]=sg[1]=0;
for (int i=2;i<=1000;i++)
{
memset(vis,0,sizeof(vis));
for (int j=0;j<=i-2;j++)
vis[sg[i-j-2]^sg[j]]=1;
for (int j=0;;j++)
if (!vis[j])
{
sg[i]=j;
break;
}
}
}
int main()
{
init();
int pp;scanf("%d",&pp);
while (pp--)
{
int now=0,ans=0;
int n;scanf("%d",&n);scanf("%s",s);
for (int i=0;i<n;i++)
{
if (s[i]=='0')
{
ans^=sg[now];
now=0;
}
else now++;
}
ans^=sg[now];
if (ans) puts("Alice");
else puts("Bob");
}
return 0;
}