这次我做博弈题开始根据特殊态猜测必胜态,失败了。
这个模型转换还是有点厉害的。
很多堆石子,两人游戏。
每次可以取走数量最多的那堆石子的全部石子,或取走每堆各一个石子。
我们把一堆石子想象成一个石子个数*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
#include
#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");
}