小花梨的取石子游戏
Description
小花梨有?堆石子,第?堆石子数量为??,?堆石子顺时针编号为1 − ?(如图)。
游戏将进行?轮,每轮游戏单独进行,互不干扰,每轮初始时第?堆石子数目为??。
第?轮从编号为?的那堆石子为起点,顺时针来取石子。两人轮流取石子,不可不取,最少取
一个石子,最多把当前这一堆取完,只有取完一堆后才走到下一堆石子。走完一圈后石子都
被取完,不能取石子的人就失败。假设两人以最优策略进行取石子操作,请分别输出?轮游
戏是先手胜还是后手胜。
Input
第一行为正整数?,表示石子的堆数 (1 ≤ ? ≤ 100000)
第二行输入?个正整数表示每一堆的石子数目??(1 ≤ ?? ≤ 109
)
Output
输出?行,第?行表示第?轮游戏的结果。如果先手胜则输出"?????",后手胜输出"??????"。
Example
Sample Input Sample Output
3
2 1 3
First
Second
First
2
2 2
First
First
Note
样例1:
游戏进行3轮
第1轮游戏石子堆下标的顺序为1 2 3,此时石子数目按顺序为2 1 3,先手胜
第2轮游戏石子堆下标的顺序为2 3 1,此时石子数目按顺序为1 3 2,后手胜
第3轮游戏石子堆下标的顺序为3 1 2,此时石子数目按顺序为3 2 1,先手胜
艰苦历程:
昨天看这个题过的人很多,觉得可以搞一下,然后wa了三发,才找到了规律…
对于每一轮游戏,先抽到非1的那一方是必胜方,所以对于每轮游戏,都要找到第一个非1的位置,然后根据距离判断赢家,如果全是1的话,那么每轮的结果都是一样,根据n的奇偶得出。
于是我用vector存…每一轮游戏都先erase一下再push_back进去,然后再从0到n-1找非1 然后显然tle了… 然后把vector改成数组…把cin cout改成scanf printf…继续tle
后经学习别人代码
存的时候把v[n]数组直接存两遍,这样就不用再删来删去。每次从i到i+n-1就好了。找非1的位置开一个b数组存,b[i]里存的数就是b[i]之后非1的位置,再根据b[i]-i的距离来判断赢家。
#include<stdio.h>
int main()
{
int n;
int v[200020];
int b[200020]={0};
int flag=1;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int a;
scanf("%d",&v[i]);
v[n+i]=v[i];
if(v[i]!=1)
flag=0;
}
if(n==1)
{
printf("First\n");
return 0;
}
long long u=-1;
if(flag!=1)
for(int i=2*n-1;i>=0;i--)
{
if(v[i]!=1)
{
u=i;
}
else
{
b[i]=u;
}
}
for(int i=0;i<n;i++)
{
if(flag)
{
if(n%2==0)
{
printf("Second\n");
continue;
}
else
{
printf("First\n");
continue;
}
}
if(v[i]!=1)
{
printf("First\n");
continue;
}
else
{
if((b[i]-i)%2!=0)
{
printf("Second\n");
continue;
}
else
{
printf("First\n");
continue;
}
}
}
return 0;
}