题意
一个箱子里面有n个硬币,你和你的对手去拿箱子里面的硬币,拿的规则如下:
1.拿一个硬币
2.如果箱子里面的硬币是偶数个,则可以拿偶数个。
从你开始拿,直到拿完为止,问在两人都玩得最优,你在游戏结束时能得到的最大硬币数量。
思路
如果是奇数的情况下,没得考虑只能拿一个。
如果是偶数的情况下,可以选择拿一半或者拿一个;这时我们直接拿一半,每次这样拿下去,这样真的是最优的方案?
其实不然,在偶数情况下,当剩下的一半是偶数时,对手将会拿走一半的一半,而当剩下的一半是奇数时,对手只能拿走一个,所以我们要制造对手拿一个,而不是一半。当箱子里面有偶数个时,这时判断n的一半是否是奇数,如果是奇数直接拿,如果是偶数只拿一个。当n等于4时需要特判。
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve() {
ll n;
scanf("%lld", &n);
ll x = 0, y = 0;
bool flag = true;
while (n > 0) {
if (flag) {
//我的回合
if ((n & 1) || (n != 4 && (n / 2) % 2 == 0)) {
x++;
n--;
} else {
x += n / 2;
n /= 2;
}
flag = false;
} else {
//对手的回合
if ((n & 1) || (n != 4 && ((n / 2) & 1) == 0)) {
y++;
n--;
} else {
y += n / 2;
n /= 2;
}
flag = true;
}
}
printf("%lld\n", x);
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) {
solve();
}
return 0;
}