题目
爱丽丝和鲍勃总是在玩游戏!今天的游戏是依次从石堆中取出石头。 有n堆石头,第I堆包含A[i]块石头。
由每堆石头的数量与其邻居的不同,他们决定在不破坏财产的情况下,一次从其中一堆石头中取出一块石头(不能在拿走一块石头后,相邻的不同石头变相同)。爱丽丝先走。 拿不到石头的玩家将输掉游戏。 你应该注意到,即使是一堆0石也还是被视为一堆!
题解
只需每次判断可以拿走多少次sum,当sum是奇数,A赢,反之B赢。
1、当a[i]都小于两边,a[i]可以变成0;
2、当a[i]都大于一边,小于一边,a[i]可以变成较小的那一边+1;
3、当a[i]都大于两边,a[i]可以变成两边最大值+1;
我们只需从头开始反复多遍历几次,就得出答案。
代码
要用scanf 和printf ,不然会被卡。
#include<bits/stdc++.h>
#define ms(a) memset(a,0,sizeof(a));
typedef long long ll;
using namespace std;
const int N = 1e5 + 5;
int a[N];
int n;
ll f() {
ll x=0;
for (int i = 1; i <= n; i++) {
int m = -1;
if (a[i] > a[i - 1])m = max(m, a[i - 1]);
if (a[i] > a[i + 1])m = max(m, a[i + 1]);
x += a[i] - m - 1;
a[i] = m + 1;
}
return x;
}
bool solve() {
ll sum = 0;
scanf("%d", &n);
a[0] = a[n + 1] = INT_MAX;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
ll x;
while (1) {
x = f();
sum += x;
if (!x)break;
}
if (sum & 1)return 1;
else return 0;
}
int main() {
int t;
cin >> t;
for (int i = 1; i <= t; i++) {
if (solve())printf("Case %d: Alice\n", i);
else printf("Case %d: Bob\n", i);
}
}