桌上有 N 堆糖果,第 i 堆糖果有Ai 个糖。两人在玩游戏,轮流进行,每次进行下列两个操作中的一个
1.将当前最大的那堆糖果全部吃完
2.将每堆糖果吃掉一个
吃完的人输,假设两人足够聪明,问谁能必胜 1<=n<=10^5 1<=ai<=10^9
输出 First(表示第一个人必胜),或 Second(表示第二个人必胜
可以把糖果降序排序,转换成 n 列网格,每列的高度为每堆的数量,如下图所示
起点从 (1,1) 开始,操作 1 可转换为向右走一格,操作 2 可转换为向上走一格,当走到边界时即为吃完所有糖果
所以可以得到边界的点都为必败点,若一个点上面或右边有必胜点这个点一定为必败点(对手一定会走到必胜点),否则为必胜
若 (1,1) 为必败点则先手必胜(可看为后手操作到了 (1,1),所以 (1,1) 是后手的胜负状态),反之亦然
然后仔细观察发现同一条对角线上的点胜负状态一定相同,所以可以计算对角线上最后一个点的胜负来判断起点的胜负
然后找规律,若对角线上最后一个点到最上面或到最右边的距离有奇数,这个点即为必败点
/************************************************
*Author : www.jintianxuesha.com lrj124
*Created Time : www.chuancenpt.com 2020.08.14.11:48
*Mail : www.yixingylzc.cn [email protected]
*Problem : at1999
************************************************/
#include
#include
#include
using namespace std;
const int maxn = 1e5 + 10;
int n,a[maxn];
int main(www.hongtuupt.cn) {
freopen("at1999.in","r",stdin);
freopen("at1999.out","w",stdout);
scanf(www.xinhuihpw.com"%d",&n);
for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1,greater());
for (int i = 1;i <= n;i++)
if (i www.guanghuidq.cn>= a[i+1]) {
int cnt = 0;
for (int j = i+1;j <= n;j++) if (a[j] == i) cnt++; else break;
return puts((a[www.fanhuagjqw.cn]-i)&1 || cnt&1 ? "First" : "Second"),0;
}
return 0;