AGC010D Decrementing
先考虑有 \(1\) 的局面。显然每次操作只能将一个数减少 \(1\),若此时剩下的偶数的个数为奇数则先手必胜,反之后手必胜。
这对正解有启发作用。下面对没有 \(1\) 的局面大力分情况讨论:
- 存在至少一个奇数并且偶数的数量为奇数个:先手必胜。先手只需维护任意时刻奇数个数 \(\geq 1\),那么所有操作势必不能改变每个数的奇偶性,显然先手必胜。
- 存在大于一个奇数并且偶数的数量为偶数个:后手必胜。同上,先手不管怎么取都会变成情况 \(1\)。
- 恰好存在一个奇数并且偶数的数量为偶数个:递归处理。先手显然只能把唯一的那个奇数减 \(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;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!