「题解」CF1033G Chip Game(手摸博弈)

神仙博弈!

考虑给定 \(a,b\)

可以证明,\(\{v_i\}\) 组成的游戏,与 \(\{v_i\bmod (a+b)\}\) 完全等价。

证明不再赘述,可以直观感性地理解。


枚举 \(s=a+b\),将 \(v_i\bmod s\) 后排序。

仍然考虑给定 \(a,b\),如何判断胜负情况。

\(A\) 必胜、\(B\) 必胜的情况本质是一致的,可以简单求解。

接下来考虑如何判断先后手必胜。

先排除掉 \(v_i<a\) 的堆,剩下的堆数记为 \(n\)

注意到:

  • 如果存在 \(a\le v_i<b\),此时 \(\bm A\) 必胜。因为,\(A\) 可以把 \(v_i\) 留在最后操作。
  • 如果存在两个及以上 \(i\)\(2a\le v_i<a+b\),此时 \(\bm A\) 必胜。如果 \(A\) 先手,\(A\) 可以选择 \(i\),转化为上面的情况;否则,\(B\) 一定会选择其中一个,\(A\) 接着选另外一个。

排除掉上面的情况,因为这不属于先手或者后手必胜。

此时,若 \(n\) 为偶数,后手必胜,否则先手必胜。

枚举 \(a,b\in (v_{i-1},v_i]\),可以算出 \(a,b\) 的下界:

  • \(n\) 为奇数,先手必胜,下界为 \(\dfrac{v_{n-1}}{2}\);否则,后手必胜,下界 \(\dfrac{v_n}{2}\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, v[110], g[110];
signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> v[i];
	int fir = 0, sec = 0;
	for (int s = 2; s <= 2 * m; s++) {
		memcpy(g, v, sizeof g);
		for (int i = 1; i <= n; i++) v[i] %= s;
		sort(v + 1, v + n + 1);
		v[n + 1] = max(v[n], m);
		for (int i = 1; i <= n + 1; i++) {
			int l = v[i - 1] + 1, r = min(m, v[i]);
			if (l > r) continue;
			if ((n - i + 1) & 1) l = max(l, v[n - 1] / 2 + 1), fir += max(0ll, min(s - l, r) - max(s - r, l) + 1);
			else l = max(l, v[n] / 2 + 1), sec += max(0ll, min(s - l, r) - max(s - r, l) + 1);
		}
		memcpy(v, g, sizeof v);
	}
	cout << (m * m - fir - sec) / 2 << " " << (m * m - fir - sec) / 2 << " " << fir << " " << sec << "\n";
	return 0;
}
posted @ 2023-06-03 22:57  Network_Error  阅读(31)  评论(0)    收藏  举报