【题解】HDU3595 GG and MM

文章介绍了两个玩家MM和GG玩的取石子游戏,规则是每次可以从较大的一堆中取走正整数倍的较小堆数量的石子。关键在于分析必胜和必败的状态,并确定哪种状态对玩家更有利。当2x≤y时,游戏是必胜的,否则必败。通过计算每个游戏的最大步数,可以决定最终的胜者。文章提供了O(nlogn)复杂度的解决方案。
摘要由CSDN通过智能技术生成

link

题目大意

MM 和 GG 在玩 N N N 个同时进行的取石子游戏。

对于一个游戏,有两堆石子 x , y ( x ≤ y ) x,y(x\le y) x,y(xy). 每一次操作可以从 y y y 中取走正整数倍的 x x x 个石子。

对于这些游戏,如果在最后一个结束的游戏中胜出,就判定为整个游戏胜出。

题解

注意游戏是同时进行

every sg 的典例。

显然,对于必胜的游戏,越晚结束越好,反之越早结束越好。

首先要知道单个游戏的小结论:若 2 x ≤ y 2x\le y 2xy,则当前必胜。否则有唯一方案( y = y − x y=y-x y=yx).

2 x > y 2x>y 2x>y,有唯一方案。此时 s g ( x , y ) sg(x,y) sg(x,y) 的值与 ( x , y ) (x,y) (x,y) 的后继的 s g sg sg 值相反。也就是 s g ( x , y ) = ! s g ( y − x , x ) sg(x,y)=!sg(y-x,x) sg(x,y)=!sg(yx,x). 显然步数加 1 1 1.

2 x ≤ y 2x\le y 2xy,若 s g ( y % x , x ) ≠ 0 sg(y\% x,x)\ne 0 sg(y%x,x)=0,步数加 2 2 2. 由于 s g ( y % x , x ) sg(y\% x,x) sg(y%x,x) 不为 0 0 0,即 ( y % x , x ) (y\% x,x) (y%x,x) 时必胜。此时只要让 y = y % x + x y=y\% x+x y=y%x+x 即可。此时对方只能走到 ( y % x , x ) (y\% x,x) (y%x,x),由你面对 ( y % x , x ) (y\% x,x) (y%x,x) 的局面,则你必胜。

s g ( y % x , x ) = 0 sg(y\% x,x)=0 sg(y%x,x)=0,步数加 1 1 1. 只需要一步走到 s g ( y % x , x ) = 0 sg(y\% x,x)=0 sg(y%x,x)=0 即可。可以证明,中间态的 s g sg sg 值一定不等于 0 0 0. 因为中间态 ( y ′ , x ) (y',x) (y,x) 一定能走到 ( y % x , x ) (y\% x,x) (y%x,x),而 ( y % x , x ) (y\% x,x) (y%x,x) 是必败态。

最后只需要将必胜局的最大步数与必败局的最大步数比较即可。

s g sg sg 函数的时间复杂度约等于 g c d gcd gcd,所以总的时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn).

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, bs;
int sg(int x, int y) {
    if (x > y) swap(x, y);
    if (!x) return 0;
    if (y < 2 * x) {
        bs++;
        return !sg(y - x, x);
    }
    if (sg(y % x, x)) bs += 2;
    else bs++;
    return 1;
}
int main() {
    while (scanf("%d", &n) != EOF) {
        int maxw = 0, maxl = 0, a, b;
        while (n--) {
            scanf("%d%d", &a, &b);
            bs = 0;
            if (sg(a, b)) maxw = max(maxw, bs);
            else maxl = max(maxl, bs);
        }
        if (maxw > maxl) printf("MM\n");
        else printf("GG\n");
    }
    return 0;
}

END

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值