题解
考虑当前面取完,只剩最后一堆时,这时该谁取,这个人只需要把最后一堆全取完,即可获胜,对于每个人,最好的方案都是让自己在剩最后一堆时先取,要想达成这个局面,则需要倒数第二堆是你的对手取完,当取完倒数第三堆,第二堆个数有两种情况:
1. 倒数第二堆剩余1:此时如果是B先取倒数第二堆,则最后一堆由A先取,A获胜,所以对于每个人,要控制到倒数第二堆时是对方先取
2.倒数第二堆剩余x个,x>1:此时如果是A先取倒数第二堆,则A可以取x-1个,倒数第二堆剩余一个,然后B只能把倒数第二堆取完,然后A先手取最后一堆,A获胜. 所以对于每个人,要控制到倒数第二堆时,是自己先取.
对于每一堆,如果这一堆需要对面先手取,如果上一堆是自己先取,则一定可以控制这一堆是自己后手取,所以上一堆一定要自己先手取. 如果这一堆需要自己先手取,则分为上一堆时剩余1,x(x>1)两种情况,同上... 以此类推如果推出到第一堆时,先手不满足必胜的条件,则是后手赢
代码
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=2e5+10;
int ssa[N];
int main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n;
vector<int>aa(1,0);
for(int i=1;i<=n;i++){
int a;
cin>>a;
aa.push_back(a);
}
sort(aa.begin()+1,aa.end());
n=unique(aa.begin()+1,aa.end())-aa.begin();
// for(int i=1;i<=n;i++)cout<<aa[i]<<' ';
// cout<<endl;
// cout<<1<<endl;
for(int i=1;i<=n;i++)ssa[i]=aa[i]-aa[i-1];
int t=1;//先手为1
for(int i=n-2;i>=1;i--){
//对于最后一堆,已经知道了到最后一堆时需要先手才能必胜,t直接设为1,从倒数第二堆(即n-2)开始递推
if(t){
// cout<<i<<ssa[i]<<endl;/**/
if(ssa[i]==1){
t=0;
}
}else {
t=1;
}
}
if(t)cout<<"Alice";
else cout<<"Bob";
cout<<endl;
}
}