POJ2234 Matches Game
题意
:
n堆石子,每次任选一堆选取任意个,不能选者输。
思路
:经典
NIM模型,石子个数异或和为
0,则先手必败,否则先手胜。此处的异或和为
0,是用归纳法进行证明的,不单只适用于
NIM问题,还在
SG函数中应用广泛,感兴趣可以自行查阅。
代码
:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
typedef long long ll;
typedef double db;
const int N = 1e5+100;
const int M = 1e5+100;
const db EPS = 1e-9;
using namespace std;
int n;
int main()
{
while(~scanf("%d",&n)){
int tp = 0;
rep(i,1,n){
int xx; scanf("%d",&xx);
tp ^= xx;
}
if(tp == 0) printf("No\n");
else printf("Yes\n");
}
return 0;
}
POJ1704 Georgia and Bob
题意
:一个一维棋盘,棋盘上有
n个棋子,已知每个棋子的初始位置。每次可以任选一个棋子向左推任意格子,但不能跨越其他棋子,不能操作者输。
思路
:仔细研究这个游戏,可以发现一个规律,就是只要前一个棋子能移动,那后一个棋子一定可以模仿前一个棋子进行移动。因此可以考虑将相邻两个棋子两两分组。
假如棋子个数为偶数,则
1、2为一组,
3、4为一组…,如果移动分组中的前一个,则我们移动后一个棋子,完全模仿前一个棋子,因此每组棋子中相隔的步数不变。因此可以将每组棋子看成一个石堆,堆中石子个数为两个棋子间距。因此如果石子个数异或和为
0,则先手输,其余均胜。
假如棋子个数为奇数,则第一个棋子与棋盘最左端构成一组,仍然可以两两分组,异或和为
0则先手输,其余先手胜。到此,即可完成此题。
反思
:本题的重点是如何构造出
NIM模型,将一个博弈游戏转化为
NIM问题,常见的入手方向是奇偶分组和两两分组。
代码
:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
typedef long long ll;
typedef double db;
const int N = 1e5+100;
const int M = 1e5+100;
const db EPS = 1e-9;
using namespace std;
int n,a[N];
int main()
{
int _; scanf("%d",&_);
while(_--)
{
scanf("%d",&n);
rep(i,1,n) scanf("%d",&a[i]);
sort(a+1,a+1+n); a[0] = 0;
int tp = 0, pos;
if(n%2 == 0) pos = 1;
else pos = 0;
while(pos <= n) tp ^= (a[pos+1]-a[pos]-1), pos = pos+2;
if(tp == 0) printf("Bob will win\n");
else printf("Georgia will win\n");
}
return 0;
}