CF1382B - Sequential Nim 题解

先特判所有数都为 \(1\) 或都不为 \(1\) 的情况。

  • 所有数都为 \(1\):判断奇偶性;
  • 所有数都不为 \(1\):先手必胜,原因略。

对于其余情况,正难则反。
\(\text{flag}_i=1/2\) 为取走第 \(i\) 堆中的最后一个石头的人(取完石头)的编号。

例如,若第 \(2\) 堆中有 \(3\) 个石头,1 取走前 \(2\) 个,2 取走最后 \(1\) 个,则 \(\text{flag}_2=\textbf{2}\)

假设 \(\text{flag}_n=1\),即 1 获胜。
枚举 \(i=n-1,n-2,\cdots,1\)。分类讨论:

  • \(\text{flag}_{i+1}=1\)
    • \(a_i=1\),即第 \(i\) 堆中有 \(1\) 个石头且第 \((i+1)\) 堆被 1 取完,则第 \(i\) 堆必然被 2 取完。原因略;
    • \(a_i>1\),即第 \(i\) 堆中有多于 \(1\) 个石头且第 \((i+1)\) 堆被 1 取完,则第 \(i\) 堆必然被 1 取完。因为若第 \(i\) 堆被 2 取完,则 2 在取第 \(i\) 堆的时候会取 \((a_i-1)\) 个石头,而留下 \(1\) 个石头给 1 取走。这样先后手关系便和假设矛盾,胜负也随之逆转。所以第 \(i\) 堆不可能被 2 取完。
  • \(\text{flag}_{i+1}=2\),即第 \((i+1)\) 堆被 2 取完,则第 \(i\) 堆必然被 1 取完。因为若第 \(i\) 堆被 2 取完,则 2 会取走 \(a_i\) 个(即取完第 \(i\) 堆),让先后手关系逆转。

枚举过后检查 \(\text{flag}_1\) 是否为 \(1\) 即得到答案(通过判断与假设是否矛盾,得到答案)。
时间复杂度线性。
Code:

#include <bits/stdc++.h>
using namespace std;
const int maxN=100005;
int flag[maxN];
int main() {
	int t; scanf("%d",&t);
for (;t;t--) {
	int n; scanf("%d",&n);
	vector<int> a(n+1);
	int one=0;
	for (int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
		if (a[i]==1) one++;
	}
	if (!one) puts("First");
	else if (one==n) puts(n&1?"First":"Second");
	else {
		flag[n]=1;
		for (int i=n-1;i;i--)
			if (flag[i+1]==1)
				if (a[i]==1) flag[i]=2;
				else flag[i]=1;
			else flag[i]=1;
		puts(flag[1]==1?"First":"Second");
	}
}
}

猜你喜欢

转载自www.cnblogs.com/Xray-luogu/p/13368926.html
Nim