TopCoder SRM 701 Div2 Problem 900 ThueMorseGame(博弈+预处理)
题意 Alice和Bob在玩一个游戏,Alice先手。
每次一个人可以从一堆式子中拿走任意数量(不超过m)的式子。
取走最后一颗式子的人胜利。
当一个取完某一步的时候剩下的石子数量的二进制表示中1的个数为奇数时,这个人直接输。
$n <= 5* 10^{8}, m <= 50$
考虑博弈
我们可以用一个01数组来表示之前50步的胜败状态。
因为m <= 50,可以直接用一个long long 来替换掉这个数组。
求二进制表示中1的个数的时候,采用预处理的方式,拆成前16位和后16位就可以了。
其他都是博弈的老套路。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 1e6 + 10; int pre[N]; class ThueMorseGame { public: string get(int n, int m){ LL all = (1LL << m) - 1; LL cnt = all; rep(i, 0, (1 << 16) - 1) pre[i]= __builtin_popcount(i); rep(i, 0, n) cnt = ((cnt << 1) & all) | (((pre[i >> 16] + pre[i & ((1 << 16) - 1)]) & 1) || (cnt ^ all)); return cnt & 1 ? "Alice" : "Bob"; } };