upc 【数论】欧几里得的游戏(博弈)

问题 E: 【数论】欧几里得的游戏

时间限制: 1 Sec  内存限制: 128 MB
提交: 50  解决: 27
[提交] [状态] [讨论版] [命题人:admin]

题目描述

欧几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的。给定两个正整数M和N,从Stan开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数不能小于0。然后是Ollie,对刚才得到的数,和M,N中较小的那个数,再进行同样的操作……直到一个人得到了0,他就取得了胜利。下面是他们用(25,7)两个数游戏的过程:
Start:25 7
Stan:11 7
Ollie:4 7
Stan:4 3
Ollie:1 3
Stan:1 0
Stan赢得了游戏的胜利。
现在,假设他们完美地操作,谁会取得胜利呢?

输入

第一行为测试数据的组数C。下面有C行,每行为一组数据,包含两个正整数M, N。(M, N不超过长整型。)

输出

对每组输入数据输出一行,如果Stan胜利,则输出“Stan wins”;否则输出“Ollie wins”

样例输入

2
25 7
24 15

样例输出

Stan wins
Ollie wins

[提交][状态]

【分析】

不妨设n>m,若n%m==0则为必胜状态。

必胜态的前一个状态肯定是(n,m+kn),即现在的必胜态肯定是m+n减掉了k倍的n得来的。如果k大于1,那么我完全可以不把m+kn的k个n都减掉而让对手拿到了必胜态,所以(n,m)的前一个状态一定是(m+n,n)。

所以,如果我遇到了一个状态(n,m),n/m==1,那我唯一的操作就是让n减掉m,这样下一个状态就有可能是必胜态。我并不想把必胜态让给对手,所以我想尽量不要遇到这样的(n,m)n/m==1;

那我就把这样的状态尽量留给我的对手,比如(10,4),那我就给对手留(6,4),而不是(2,4);

然后,讨论一下n/m>1的情况:那我就可以掌控大局了,我从n中拿掉一些m,使得剩下的n/m==1或者m/n==1,这样对手就别无选择了,只能从大数中减掉一个小数,对手剩给我的就有可能是个必胜态,或者又是个n/m>1,或者n/m==1(这种情况因为我是先手,我可以预判一下,我是不会让这种事情发生的),因此我总是有办法赢。

【代码】

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
int main()
{
    int T;
    ll n,m;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m);
        if(n<m)swap(n,m); //n%m==0必胜
        int res=1;
        while(n%m&&n/m==1)
        {
            n-=m;
            if(n<m)swap(n,m);
            res^=1;
        }
        printf("%s wins\n",res?"Stan":"Ollie");
    }
}

 

 

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪的期许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值