AGC002 E Candy Piles 思维题 博弈

题目链接

题意:
桌上有N 堆糖果,第i 堆糖果有Ai 个糖。两人在玩游戏,轮流进行,每次进行下列两个操作中的一个
1.将当前最大的那堆糖果全部吃完
2.将每堆糖果吃掉一个
吃完的人输,假设两人足够聪明,问谁能必胜 1<=n<=1e5
输出First(表示第一个人必胜),或Second(表示第二个人必胜)

题解:
这题感觉没有图不好讲啊,真是道很神的题啊。先放个官方题解的链接。下面的图片来自官方题解。
官方题解

我们可以把a数组先从大到小排序,排序后可以看作下图,其中高度表示 a i a_i ai的数值。
图片
我们之后可以把删除一堆和每一堆去掉一个看作下图:
图片

然后我们可以把一开始的图看作一个方格图,把删除一堆看作向右走,把每一堆减少一个看作向上走一步,轮廓线对应原图中的结束状态。如下图所示:
图片

对于这种博弈思想的题,经常是判断每个状态是先手必胜还是先手必败,这里也是用这种思路,我们用’x’表示先手必败,用’o’表示先手必胜。首先显然对于终结节点是先手必胜,因为已经所有的糖都被吃掉了。然后我们可以暴力计算其他所有点的状态,但是这题显然会T。我们考虑观察这个状态图(如下),我们会发现,在同一条对角线上的点的状态都是一样的,要么都是必胜,要么都是必败。那么我们只需要一直沿着对角线走,直到走到边缘。我们发现走到边缘之后,如果走到最上方或者最右侧有至少一种能用奇数步完成,那么就是必胜的,否则就是必败的。于是就可以快速计算这题的答案了。
图片

代码:

#include <bits/stdc++.h>
using namespace std;

int n,a[100010];
int main()
{
 scanf("%d",&n);
 for(int i=1;i<=n;++i)
 scanf("%d",&a[i]);
 sort(a+1,a+n+1);
 reverse(a+1,a+n+1);
 for(int i=1;i<=n;++i)
 {
  if(i+1>a[i+1])
  {
   int ji=i+1,pd=0;
   while(a[ji]==i)
   {
    pd^=1;
    ++ji; 
   } 
   if(pd||(a[i]-i)%2==1)
   printf("First\n");
   else
   printf("Second\n");
   break;
  }
 }
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值