题意是有无数个排成直线的格子,上面有n枚棋子,告诉你棋子的位置,Georgia和Bob轮流选择一枚棋子,使之左移一定长度,不能反超前面的棋子,谁不能走谁输,Georgia先走,输出赢家。
思路:我们按棋子奇偶去分类讨论。
偶数时,我们把每两个相邻的棋子作为一组,相当于Nim中的一堆,大小为两点间距离。则右边棋子移动就相当于从Nim的一堆石子中取若干个石子,左边棋子移动相当于把这一堆加上若干石子,但是对手又可以取走同样多的石子,故两种状态等效,不用考虑。
奇数时,我们在序列最左端放一枚石子,然后就和偶数时的情况相同了。
Nim博弈的证明及结论可以参考http://www.cnblogs.com/exponent/articles/2141477.html
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; ///#define Online_Judge #define outstars cout << "***********************" << endl; #define clr(a,b) memset(a,b,sizeof(a)) #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1 | 1 #define mk make_pair #define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++) #define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++) #define REP(i , x , n) for(int i = (x) ; i > (n) ; i--) #define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--) const int MAXN = 1000 + 50; const int MAXS = 10000 + 50; const int sigma_size = 26; const long long LLMAX = 0x7fffffffffffffffLL; const long long LLMIN = 0x8000000000000000LL; const int INF = 0x7fffffff; const int IMIN = 0x80000000; const int inf = 1 << 30; #define eps 1e-8 const long long MOD = 1000000000 + 7; const int mod = 100000; typedef long long LL; const double PI = acos(-1.0); typedef double D; typedef pair<int , int> pii; #define Bug(s) cout << "s = " << s << endl; ///#pragma comment(linker, "/STACK:102400000,102400000") int n , p[MAXN]; void solve() { if(n & 1)p[n++] = 0; sort(p , p + n); int ans = 0; for(int i = 0 ; i < n - 1; i += 2) { ans ^= (p[i + 1] - p[i] - 1); } if(ans)puts("Georgia will win"); else puts("Bob will win"); } int main() { int t; cin >> t; while(t--) { scanf("%d" , &n); for(int i = 0 ; i < n ; i++) { scanf("%d",&p[i]); } solve(); } return 0; }