题目链接
前置trick:
使用vector去重:
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
sort(a.begin(),a.end());
a.erase(unique(a.begin(),a.end()),a.end());
n=a.size();
题意:
有
n
n
n堆石子,第
i
i
i堆有
a
i
a_i
ai颗。Alice 和 Bob 两人轮流,Alice 先手。每一轮玩家从所有非空堆中拿走相同数量的石子,不能行动的失败。若两位玩家均使用最优策略,求最终获胜者。
题解:
首先考虑如何简化问题,由于是从所有非空堆拿走石头,所以重复数量石头堆可以去重。然后最少的石头堆只有一个石头的情况下只有一种操作,即所有石头堆都取走一个石头,直到没有石头或最少数量大于1的情况。在新的情况下,考虑从所有石子堆中取出一颗石子的新状态为
S
S
S,若
S
S
S为必败态,则当前状态为必胜态。
否则,
S
S
S的后继状态中必然存在必败态,记为
S
′
S^{\prime}
S′。我们发现
S
S
S的后继状态集合包含在当前状态的后继状态集合中!这样,当前状态的后继集合中必然存在必败态,当前状态就是必胜态。(好像是结论)那么只需要一开始模拟完最小堆为1的情况即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define db double
const int mod=1e9+7;
const int N=4e5;
const db PI=acos(-1);
int T,n;
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--)
{
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
sort(a.begin(),a.end());
a.erase(unique(a.begin(),a.end()),a.end());
n=a.size();
int sum=0;
for(int i=0;i<n;i++)
{
if(a[i]!=i+1) break;
sum++;
}
if(a[n-1]==n) sum++;
cout<<((sum%2==0)?"Alice":"Bob")<<"\n";
}
}