1 条题解
-
1
题目分析
发现题目很像 Nim 游戏,有区别在于每次取石子只能取某些给定的数值。但看数据范围发现 很小,可以直接递推求 SG 函数。
然后根据 SG 定理 求出子游戏的 Nim 和(记为 )。- :先手必败
- :先手必胜。至于求第一步的方案,可以直接枚举取哪一堆、取多少石子,判断是否能使 就行了。
代码
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <bitset> const int N = 10; const int SIZ = 1e3; int A[N + 5], n; int B[N + 5], m; int SG[SIZ + 5]; void GetSG(); int main() { std::ios::sync_with_stdio (0), std::cin.tie (0); std::cin >> n; for (int i = 1; i <= n; ++i) std::cin >> A[i]; std::cin >> m; for (int i = 1; i <= m; ++i) std::cin >> B[i]; GetSG(); int sxor = 0; for (int i = 1; i <= n; ++i) sxor ^= SG[A[i]]; if (!sxor) std::cout << "NO"; else { std::cout << "YES" << "\n"; int k = (int)log2 (sxor); bool flag = false; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m && B[j] <= A[i]; ++j) if ((SG[A[i] - B[j]] ^ SG[A[i]] ^ sxor) == 0) { std::cout << i << " " << B[j], flag = true; break; } if (flag) break; } }std::cout << "\n"; return 0; }void GetSG() { std::bitset <SIZ + 1> S; for (int i = 1; i <= SIZ; ++i) { S.reset(); for (int j = 1; j <= m && B[j] <= i; ++j) S.set (SG[i - B[j]]); S.flip(), SG[i] = S._Find_first(); } }
- 1
信息
- ID
- 1874
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 19
- 已通过
- 9
- 上传者