【HDU3595】GG and MM(博弈论)

题面

HDU
一个游戏由多个游戏组成,每次每个操作者必须操作所有可以操作的游戏,操作集合为空者输。
每个游戏由两堆石子组成,每次可以从较多的那一堆中取走较小那堆的数量的倍数个石子。
判断胜负。

题解

EverySG E v e r y − S G ,所以我们只需要分开考虑两堆。
这题有点性质,假设两堆石子为 x,y,x<y x , y , x < y ,那么令 k=yx k = ⌊ y x ⌋
如果 k=1 k = 1 ,显然操作唯一,直接取反后继的 sg s g 函数即可。
如果 k>1 k > 1 ,显然先手可以控制是把所有倍数都取完还是强制将 k k 变成1,让后手做一次确定操作,所有此时先手必胜,那么只需要考虑 k=1 k = 1 时的后继状态的 N/P N / P 情况,做出相应的抉择就好了。
同理维护 step s t e p 值即可。
最后判断 step s t e p 最大值来判定胜负情况。

#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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值