[agc002e]Candy Piles

来源:互联网 发布:网络机顶盒换系统 编辑:程序博客网 时间:2024/06/05 04:09

前言

这次我做博弈题开始根据特殊态猜测必胜态,失败了。
这个模型转换还是有点厉害的。

题目大意

很多堆石子,两人游戏。
每次可以取走数量最多的那堆石子的全部石子,或取走每堆各一个石子。

模型转换

我们把一堆石子想象成一个石子个数*1的矩形。
把矩形从高到低排列变成一个图形。
我们每次可以删除最低下一行或最左边一列。
假设有一个点初始在(1,1),它在(x,y)表示[1,x)的列被删了,[1,y)的行被删了。
则每次相当于将这个点往上移或往右移,不能操作者输。
我们给每个点打上0/1的标记,1表示先手必胜,现在需要判断(1,1)的标记。

结论

(x-1,y-1)的标记与(x,y)一样。
假如(x,y)是0,(x-1,y-1)一定是0。
因为在(x-1,y-1)这个位置上,无论先手怎么动,后手都刻意移到(x,y)。
假如(x,y)是1,(x-1,y-1)不可能是0。
0 ?
1 1 ?
0 1 0
注意到0的后继全都是1,1的后继一定有0。
可以画出这样的图。
发现两个?处至少有一个0(1的后继一定有0),但两个?处都必须是1(0的后继全部是1),因此矛盾。
然后我们就证明了这个结论。
接下来就很好做了,找到最大的(i,i),使得i+1>a[i+1]。
那么判断(i,i)的标记即可。
此时只有一路往上和一路往右两个选择。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=100000+10;int a[maxn];bool czy;int i,j,k,l,t,n,m;int main(){    scanf("%d",&n);    fo(i,1,n) scanf("%d",&a[i]);    sort(a+1,a+n+1);    reverse(a+1,a+n+1);    fo(i,1,n)        if (i+1>a[i+1]){            if ((a[i]-i)%2==1){                czy=1;                break;            }            czy=0;            fo(j,i+1,n)                if (a[j]==i) czy^=1;else break;            break;        }    if (czy) printf("First\n");else printf("Second\n");}