链接:传送门
单点时限: 1.0 sec
内存限制: 512 MB
Description
小花梨有n堆石子,第i堆石子数量为ai,n堆石子顺时针编号为1−n(如图)。
游戏将进行n轮,每轮游戏单独进行,互不干扰,每轮初始时第i堆石子数目为ai。第i轮从编号为i的那堆石子为起点,顺时针来取石子。两人轮流取石子,不可不取,最少取一个石子,最多把当前这一堆取完,只有取完一堆后才走到下一堆石子。走完一圈后石子都被取完,不能取石子的人就失败。假设两人以最优策略进行取石子操作,请分别输出n轮游戏是先手胜还是后手胜。
Input
第一行为正整数n,表示石子的堆数(1≤n≤100000)第二行输入n个正整数表示每一堆的石子数目ai(1≤ai≤109)
Output
输出n行,第i行表示第i轮游戏的结果。如果先手胜则输出"First",后手胜输出"Second"。
Example
Sample InputSample Output
3
2 1 3
First
Second
First
2
2 2
First
First
Note
样例1:
游戏进行3轮第1轮游戏石子堆下标的顺序为123,此时石子数目按顺序为213,先手胜
第2轮游戏石子堆下标的顺序为231,此时石子数目按顺序为132,后手胜
第3轮游戏石子堆下标的顺序为312,此时石子数目按顺序为321,先手胜
思路
我们先假设第一个数字为3,后一个数字为1,根据题意第一个人第一次需要拿2个,才能取得胜利,而如果数字排序是311的话,第一个人第一次则需要拿3个,才能取得胜利。不过由此可以看出,第一个人可以通过一个不为1的数来调节谁最后不能够拿到石子,即谁最后取得胜利。因此我们需要记录刚开始时连续的1有几个(像111221 满足该条件有3个1 112211 满足条件有2个1 222211没有满足条件的1),来确定遇到第一个不是1的数字时谁是先手状态,也就是最后谁能获胜了。该题的数据范围是n<=1e5 如果直接暴力里写的话时间复杂度是(n^2),会超出1秒的时间限制,即TL。所以需要开一个数组记录一下当前位置时连续的1有几个。
具体实现方法如下:
for(int i=0; i<n; i++)
{
if(a[i]==1)
{
if(i==0||a[i-1]!=1)
{
int tep=1;
for(int j=i+1; j<n; j++)
{
if(a[j]!=1)
break;
else
tep++;
}
dis[i]=tep;
}
else
dis[i]=dis[i-1]-1;
}
else
dis[i]=0;
}
而对于开头出的石子,因为下一次循环时会变成末尾的的石子,因此需要对初始序列末尾的石子加一个特判,特判如下(比如说11233111,如果按上面的那个方法当轮到后3位开始时满足条件的1分别为3,2,1,可实际上却是5,4,3因此需要特别处理一下)
for(int i=n-1;i>=1;i--)
{
if(dis[i]!=0)
{
dis[i]=min(dis[0]+dis[i],n);
}
else
break;
}
而最后判断谁胜利只需要判断谁第一个非1数字开始谁是先手就可以了,而如果没有大于1的数字判断,就只需要判断一个个数了。实现代码如下:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<iostream>
#define N 100001
using namespace std;
int dis[N], mark, a[N];
int n;
int main()
{
scanf("%d", &n);
int flag=0;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if(a[i]!=1)
flag=1;
}
for(int i=0; i<n; i++)
{
if(a[i]==1)
{
if(i==0||a[i-1]!=1)
{
int tep=1;
for(int j=i+1; j<n; j++)
{
if(a[j]!=1)
break;
else
tep++;
}
dis[i]=tep;
}
else
dis[i]=dis[i-1]-1;
}
else
dis[i]=0;
}
for(int i=n-1;i>=1;i--)
{
if(dis[i]!=0)
{
dis[i]=min(dis[0]+dis[i],n);
}
else
break;
}
// for(int i=0;i<n;i++)
// printf("%d ",dis[i]);
// printf("\n");
for(int i=0;i<n;i++)
{
if(flag)
{
if(dis[i]%2==0)
printf("First\n");
else
printf("Second\n");
}
else
{
if(dis[i]%2==0)
printf("Second\n");
else
printf("First\n");
}
}
return 0;
}