HDU
一个游戏由多个游戏组成,每次每一个操做者必须操做全部能够操做的游戏,操做集合为空者输。
每一个游戏由两堆石子组成,每次能够从较多的那一堆中取走较小那堆的数量的倍数个石子。
判断胜负。php
\(Every-SG\),因此咱们只须要分开考虑两堆。
这题有点性质,假设两堆石子为\(x,y,x<y\),那么令\(k=\lfloor\frac{y}{x}\rfloor\)
若是\(k=1\),显然操做惟一,直接取反后继的\(sg\)函数便可。
若是\(k>1\),显然先手能够控制是把全部倍数都取完仍是强制将\(k\)变成\(1\),让后手作一次肯定操做,全部此时先手必胜,那么只须要考虑\(k=1\)时的后继状态的\(N/P\)状况,作出相应的抉择就行了。
同理维护\(step\)值便可。
最后判断\(step\)最大值来断定胜负状况。ios
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MAX 1010 int n,m,sg[MAX][MAX],step[MAX][MAX]; int Getsg(int x,int y) { if(x>y)swap(x,y); if(~sg[x][y])return sg[x][y]; if(!x||!y)return sg[x][y]=0; int r=y%x,d=y/x; if(d==1) { sg[x][y]=Getsg(r,x)^1; step[x][y]=step[r][x]+1; return sg[x][y]; } else { step[x][y]=Getsg(r,x)+1+step[r][x]; return sg[x][y]=1; } } int main() { memset(sg,-1,sizeof(sg)); ios::sync_with_stdio(false); while(cin>>n) { int mx=0,a,b; while(n--) { cin>>a>>b;if(a>b)swap(a,b);Getsg(a,b); mx=max(mx,step[a][b]); } if(mx&1)cout<<"MM"<<endl; else cout<<"GG"<<endl; } return 0; }