https://codeforces.com/gym/104053/problem/H
题目大意:现又一个含有n个数的集合,AB两人轮流将一个任意的数放入集合中,A先手,每人放k个数后结束,如果最后在集合中没出现的最小整数为偶数,则A赢,否则B赢,问谁能赢
1<=n,k<=2e5;0<=ai<=1e6
思路:因为要找最小的没出现过的数,要使一个数成为最终的判定数,小于他的数必须都出现过,所以我们无论怎么放,都等价于从最小的数开始逐个往大放,我们从0开始遍历,对于没有在集合中的数,如果是偶数,那么A就直接放,这样的话B会放入下一个奇数,然后最终的判定数就是偶数,A赢,反之如果是奇数,那么B也要放入,使A放下一个偶数,这样最终判定数就是奇数,综上,A的最优策略就是放偶数,B的最优策略就是放奇数,我们从0开始遍历每个没在集合中的数,然后让AB进行他们所有的K个回合后,再重新遍历,看哪个数第一个没有出现
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
map<int, int>ma;
int main()
{
int t;
cin >> t;
while (t--)
{
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
ma[x] = 1;//记录集合中有哪些数
}
int now = 0;
int opa = k, opb = k;//AB剩余的回合数
while (opa || opb)
{//从0开始往大遍历直到两人剩余回合数都为0
while (ma[now] != 0)
now++;
if (opb != 0 && now & 1)
{//是奇数就B放
opb--;
ma[now] = 1;
}
else if (opa != 0 && (now & 1) == 0)
{A放偶数
opa--;
ma[now] = 1;
}
now++;
}
now = 0;
while (ma[now] != 0)
{//从小到大遍历集合中的数
now++;
}
if (now & 1)
{//第一个没出现的数是奇数就B赢
printf("Bob\n");
}
else
{
printf("Alice\n");
}
ma.clear();
}
return 0;
}