AGC010D Decrementing

题目链接

先考虑有 (1) 的局面。显然每次操作只能将一个数减少 (1),若此时剩下的偶数的个数为奇数则先手必胜,反之后手必胜。

这对正解有启发作用。下面对没有 (1) 的局面大力分情况讨论:

  1. 存在至少一个奇数并且偶数的数量为奇数个:先手必胜。先手只需维护任意时刻奇数个数 (geq 1),那么所有操作势必不能改变每个数的奇偶性,显然先手必胜。
  2. 存在大于一个奇数并且偶数的数量为偶数个:后手必胜。同上,先手不管怎么取都会变成情况 (1)
  3. 恰好存在一个奇数并且偶数的数量为偶数个:递归处理。先手显然只能把唯一的那个奇数减 (1),从而使得一些数的奇偶性改变来试图扭转战局。

显然最后一种情况的次数是 (log) 级别的,可以暴力处理。时间复杂度 (O(nlogV))

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100009;
int n, a[N];

void init()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
}

void work()
{
	if (n == 1)
	{
		if (a[1] == 1) puts("Second");
		else puts("First");
		return;
	}
	int qwq = 0;
	while (1)
	{
		int flag = 0;
		for (int i = 1; i <= n; i++)
			if (a[i] == 1) { flag = 1; break; }
		int tmp = 0, pos = -1;
		for (int i = 1; i <= n; i++)
			if (a[i] & 1)
				tmp++, pos = i;
		if (flag)
		{
			if (n - tmp + qwq & 1) puts("First");
			else puts("Second");
			return;
		}
		if (tmp > 1)
		{
			if (n - tmp + qwq & 1) puts("First");
			else puts("Second");
			return;
		}
		if (n - 1 & 1)
		{
			if (qwq) puts("Second");
			else puts("First");
			return;
		}
		a[pos]--;
		int k = a[1];
		for (int i = 2; i <= n; i++)
			k = __gcd(k, a[i]);
		for (int i = 1; i <= n; i++)
			a[i] /= k;
		qwq++;
	}
}

int main()
{
	init();
	work();
	return 0;
}

原文地址:https://www.cnblogs.com/With-penguin/p/13818393.html