GG and MM
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 645 Accepted Submission(s): 275
Problem Description
GG and MM like playing a game since they are children. At the beginning of game, there are two piles of stones. MM chooses a pile of stones first, which has x stones, and then she can choose a positive number k and remove k*x stones out from the other pile of stones, which has y stones (I think all of you know that y>=k*x - -!). Then it comes the turn of GG, followed the rules above-mentioned as well. When someone can’t remove any stone, then he/she loses the game, and this game is finished.
Many years later, GG and MM find this game is too simple, so they decided to play N games at one time for fun. MM plays first, as the same, and the one on his/her turn must play every unfinished game. Rules to remove are as same as above, and if someone cannot remove any stone (i.e., loses the last ending game), then he/she loses. Of course we can assume GG and MM are clever enough, and GG will not lose intentionally, O(∩_∩)O~
Input
The input file contains multiply test cases (no more than 100).
The first line of each test case is an integer N, N<=1000, which represents there are N games, then N lines following, each line has two numbers: p and q, standing for the number of the two piles of stones of each game, p, q<=1000(it seems that they are so leisure = =!), which represent the numbers of two piles of stones of every game.
The input will end with EOF.
Output
For each test case, output the name of the winner.
Sample Input
3
1 1
1 1
1 1
1
3 2
Sample Output
MM
GG
题意:两个人玩游戏,每次只能在石子数多的那一堆取出石子数少的那一堆的
k
倍的石子,同时有
思路:这是一种叫做Every-SG博弈的游戏,在贾志豪的论文有提到,对于我们一定会输的局面,我们要使得这个局面尽快结束,也就是说进行的步数最少,对于我们一定会赢的局面,我们要使得这个局面进行的尽可能慢,也就是说进行的步数最多,然后最多的步数如果为奇数,则先手必胜,反之先手必输。对于这道题的游戏,我们不用必须求出SG值,只需要用SG值保存当前局面的胜负即可,然后判断下一个局面的胜负情况,如果下一个局面为负,即当前局面为必胜局面,那么记录最大的步数,否则记录最小的步数。
ac代码:
/* ***********************************************
Author : AnICoo1
Created Time : 2016-08-11-16.20 Thursday
File Name : D:\MyCode\2016-8月\2016-8-11.cpp
LANGUAGE : C++
Copyright 2016 clh All Rights Reserved
************************************************ */
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define MAXN 1010000
#define LL long long
#define ll __int64
#define INF 0xfffffff
#define mem(x,y) memset(x,(y),sizeof(x))
#define PI acos(-1)
#define eps 1e-8
using namespace std;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
double dpow(double a,ll b){double ans=1.0;while(b){if(b%2)ans=ans*a;a=a*a;b/=2;}return ans;}
//head
int sg[1010][1010],step[1010][1010];
int getstep(int a,int b)
{
if(sg[a][b]!=-1) return sg[a][b];
if(a>b) swap(a,b);
int M=-1,mi=INF;
for(int i=a;i<=b;i+=a)
{
int k=getstep(a,b-i);
if(k==0) M=max(M,step[a][b-i]),sg[a][b]=sg[b][a]=1;
else mi=min(mi,step[a][b-i]);
}
if(sg[a][b]==1)
step[a][b]=step[b][a]=M+1;
else
{
step[a][b]=step[b][a]=mi+1;
sg[a][b]=sg[b][a]=0;
}
return sg[a][b];
}
int main()
{
int n;
while(cin>>n)
{
mem(sg,-1);int ans=-1;
for(int i=0;i<=1000;i++)
sg[i][0]=sg[0][i]=0,step[i][0]=step[0][i]=0;
for(int i=0;i<n;i++)
{
int a,b;cin>>a>>b;
getstep(a,b);
ans=max(ans,step[a][b]);
}
if(ans%2) printf("MM\n");
else printf("GG\n");
}
return 0;
}