http://acm.hdu.edu.cn/showproblem.php?pid=1536
http://acm.hdu.edu.cn/showproblem.php?pid=1944
一样的题
题意:先给一个集合,代表可能发生的转移。然后m个询问,可以理解为每次给l堆石子,每堆有hi个,问博弈策略
直接用sg定理,非常简单,转移给的清清楚楚,照着写就行,递推或者记忆化搜索都行。
这题的时间卡的紧,开始死活过不了,看别人代码把vis数组开成100就过了(原来开的1w),深感此题有问题,sg的值最大应该1w才对(或者我想错了欢迎指出?)
AC 代码
#include <iostream> #include <cstdio> #include <cstring> #include <set> #include <algorithm> using namespace std; int sg[10005], vis[105], s[105], k; void getSG() { sg[0] = 0; for(int j = 1; j <= 10000; j++) { memset(vis, 0, sizeof(vis)); for(int i = 0; i < k; i++) { if(s[i] <= j) vis[sg[j-s[i]]] = 1; } for(int i = 0; ; i++) { if(!vis[i]) { sg[j] = i; break; } } } } int main() { while(~scanf("%d", &k), k) { for(int i = 0; i < k; i++) scanf("%d", &s[i]); getSG(); int m; scanf("%d", &m); while(m--) { int l; scanf("%d", &l); int ans = 0; while(l--) { int h; scanf("%d", &h); ans ^= sg[h]; } if(!ans) putchar('L'); else putchar('W'); } putchar('\n'); } return 0; }