“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学)

D. 小花梨的取石子游戏

Description
小花梨有𝑜堆石子,第𝑗堆石子数量为𝑏𝑗,𝑜堆石子顺时针编号为1 − 𝑜(如图)。
游戏将进行 游戏将进行𝒏轮, 轮, 每轮游戏 单独进行 ,互不干扰 ,每轮初始时第 每轮初始时第𝒊 堆石子数目为𝒂𝒊。 。
第𝑗轮从编号为𝑗的那堆石子为起点,顺时针来取石子。两人轮流取石子,不可不取,最少取
一个石子,最多把当前这一堆取完,只有取完一堆后才走到下一堆石子。走完一圈后石子都
被取完,不能取石子的人就失败。假设两人以最优策略进行取石子操作,请分别输出𝑜轮游
戏是先手胜还是后手胜。
Input
第一行为正整数𝑜,表示石子的堆数 (1 ≤ 𝑜 ≤ 100000)
第二行输入𝑜个正整数表示每一堆的石子数目𝑏𝑗(1 ≤ 𝑏𝑗 ≤ 10 9 )
Output
输出𝑜行,第𝑗行表示第𝑗轮游戏的结果。如果先手胜则输出"𝐹𝑗𝑠𝑡𝑢",后手胜输出"𝑇𝑓𝑑𝑝𝑜𝑒"。
Example
Sample Input Sample Output
3
2 1 3
First
Second
First
2
2 2
First
First
Note
样例1:
游戏进行3轮
第11 2 32 1 3,先 第22 3 11 3 2,后 第3轮游戏石子堆下标的顺序为3 1 2,此时石子数目按顺序为3 2 1,先手胜

思路:

现在只考虑每一轮游戏

1.一堆的时候是必胜态

多堆的时候

起点数目大于1,是必胜态
因为可以取完或者取得只剩下一个,这两种状态的胜负一定同,也就是说一定可以到达必败态,所以此时为必胜态

若起点数目等于1,则和下一点的状态相反

那么我们可以先把a数组长度扩展为2倍(复制一遍在后面,因为要处理以每一个i为起始位置)从后向前维护一下1的连续个数即可。

当整个数组全为1的时候,特判n的奇偶出答案即可。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int a[maxn];
int n;
int b[maxn];
int flag=1;
int main()
{
	//freopen("D:\\code\\text\\input.txt","r",stdin);
	//freopen("D:\\code\\text\\output.txt","w",stdout);
	
	gbtb;
	cin>>n;
	repd(i,1,n)
	{
		cin>>a[i];
		a[i+n]=a[i];
	}
	for(int i=n*2;i>=1;--i)
	{
		if(a[i]==1)
		{
			b[i]=b[i+1]+1;
		}else
		{
			b[i]=0;
			flag=0;
		}
	}
	if(flag)
	{
		repd(i,1,n)
		{
			if(!(n&1))
			{
				cout<<"Second"<<endl;
			}else
			{
				cout<<"First"<<endl;
			}
		}
	}else
	{
		repd(i,1,n)
		{
			if(!b[i])
			{
				cout<<"First"<<endl;
				continue;
			}
			if(b[i]&1)
			{
				cout<<"Second"<<endl;
			}else
			{
				cout<<"First"<<endl;
			}
		}
	}

	return 0;
}
 
inline void getInt(int* p) {
	char ch;
	do {
		ch = getchar();
	} while (ch == ' ' || ch == '\n');
	if (ch == '-') {
		*p = -(getchar() - '0');
		while ((ch = getchar()) >= '0' && ch <= '9') {
			*p = *p * 10 - ch + '0';
		}
	}
	else {
		*p = ch - '0';
		while ((ch = getchar()) >= '0' && ch <= '9') {
			*p = *p * 10 + ch - '0';
		}
	}
}