【HDU3595】GG and MM(博弈論)

【HDU3595】GG and MM(博弈論)

題面

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;
}
相關文章
相關標籤/搜索