题意:有n堆石子,每次可以将其中一堆分为数量不为0的3堆,或者从其中一堆中拿走若干个,最终拿完的那个人赢。
思路:直接暴力SG状态,然后找出其中的规律,异或一下每一堆的状态就可以了。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e3 + 7;bool flag[maxn]; int sg[maxn]; int getSg(int x){ if(sg[x] != -1) return sg[x]; memset(flag, 0, sizeof(flag)); for(int i = 1; i < x; i ++){ int sgi = getSg(i); for(int j = 1; j < x - i; j ++){ int sgj = getSg(j); int sgk = getSg(x - i - j); flag[sgi^sgj^sgk] = true; } flag[i] = true; } for(int i = 1; ;i ++) if(!flag[i]) return i; } int main(){ int T = 100, n; memset(sg, - 1, sizeof(sg)); for(int i = 0; i <= T; i ++){ printf("%d %d ", i, sg[i] = getSg(i)); } return 0; }
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e3 + 7;int getSg(int x){ if(x <= 2) return x; else if(x % 8 == 7) return x + 1; else if(x % 8 == 0) return x - 1; else return x; } int main(){ int T, n, m;scanf("%d", &T); for(int ncase = 1; ncase <= T; ncase ++){ scanf("%d", &n); int sta = 0; for(int i = 0; i < n; i ++){ scanf("%d", &m); sta ^= getSg(m); } printf("%s ", sta?"First player wins.":"Second player wins."); } return 0; }