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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winter2121/article/details/81950819

问题 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");
    }
}

猜你喜欢

转载自blog.csdn.net/winter2121/article/details/81950819
UPC