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; }