HDU 3595 GG and MM [Every-SG]

传送门

题意:

两个数$x,y$,一个人的决策为让大数减去小数的任意倍数(结果不能为负),出现0的人胜

一堆这样的游戏同时玩


 

Every-SG 游戏规定,对于还没有结束的单一游戏,游戏者必须对该游戏进行一步决策;

贪心:先手必胜的尽量长,先手必败的尽量短

对于Every-SG 游戏先手必胜当且仅当单一游戏中最大的step 为奇数。

 


$step(u) =$

\begin{cases}
0, & \text{$u为终止状态$}\\
max\{step(v)\}+1, & \text{ $sg(u)\neq 0\land v为u的后继\land sg(v)=0$ }\\
min\{step(v)\}+1, & \text{$sg(u)=0\land v为u的后继$}
\end{cases}

 

单个游戏,好熟悉啊,这不那个欧几里得游戏嘛

容易发现$a/b > 2$必胜,因为这时候掌握了主动权

然后$dfs$就好啦

$pair$还挺快的嘛

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define pii pair<int,int> 
#define MP make_pair 
#define fir first
#define sec second
typedef long long ll;
const int N=1e3+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int n;
pii sg[N][N];
pii dfs(int a,int b){
    if(a<b) swap(a,b);
    pii &now=sg[a][b];
    if(now.fir!=0 || b==0) return now;

    int k=a/b;pii f=dfs(b,a%b);
    if(k==1) now=MP(f.fir^1,f.sec+1);
    else{
        now=MP(1,f.sec+1);
        if(f.fir) now.sec++;
    }
    return now;
}
int main(){
    freopen("in","r",stdin);
    while(scanf("%d",&n)!=EOF){
        int mx=0;
        for(int i=1;i<=n;i++) mx=max( mx,dfs(read(),read()).sec );
        if(mx&1) puts("MM");
        else puts("GG");
    }
}

 

posted @ 2017-03-14 10:22  Candy?  阅读(174)  评论(0编辑  收藏  举报