【博弈】AGC002E Candy Piles
阿新 • • 發佈:2018-12-09
題意:
給出N個數,兩人依次選擇一種操作: 1、刪去最大的一個數 2、所有數-1
不能走的算獲勝,求誰必勝。
分析:
有趣。。。這題真心有趣。。。
首先,把這N個數從大到小排序,畫成一個圖: 每種操作就相當於:刪去最左邊一列,或刪去最下面一行。
然後觀察剩餘部分的左下角座標:發現它是從(0,0)出發,每次向上走(刪去最下面一行),向右走(刪去最左邊一列),最終到達邊界的一條路徑。
所以就可以把每個點存一個NP狀態。 邊界的都為必勝,然後按照NP狀態的定義進行轉移。
但就這麼轉移肯定會T
然後可以把NP狀態畫一下,發現:每一個斜對角線(除去邊界)NP狀態都是一樣的
如果點(x,y)是必敗,那麼(x+1,y)與(x,y+1)都為必勝,根據上面所證明的,則(x+2,y+1),(x+1,y+2)均為必勝,那麼(x+1,y+1)則為必敗。
所以就可以直接根據(0,0)所在的斜對角線,求出其對應的未到達邊界的最高的一個點,然後從那個點出發,觀察其上方還剩多少個點,右方還剩多少個點,當且僅當兩者均為奇數時,答案為必敗,否則為必勝
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
int a[MAXN];
bool cmp(int x,int y){
return x>y;
}
int main(){
int n,m,q;
SF("%d",&n);
for(int i=1;i<=n;i++)
SF("%d" ,&a[i]);
sort(a+1,a+1+n,cmp);
a[0]=a[1];
for(int i=0;;i++)
if(i+2>a[i+2]){
int x=i;
int len1=a[i+1]-x;
int len2=1;
for(;a[i+len2+1]>x;len2++);
if(len1%2==1&&len2%2==1)
PF("Second");
else
PF("First");
break;
}
}