例1.3-1欧几里德游戏

问题描述:

Stan和Ollie玩数字游戏。

给定两个正整数M和N,从Stan先开始,去其中较大的一个数减去较小数得正整数倍,当然,得到的数不能小于0。然后是Ollie,对刚才得到的数K,以及M和N中较小的数,再进行相同的操作......知道有一个人得到了0,他就取得了胜利。

假设他们完美操作,谁会取得胜利呢?

要求:输入测试数据得组数C;

下面有C行,每行包括一组数据M和N,M和N的范围不超过长整型;

每组输出一行:"Stan wins"或者"Ollie wins".

问题分析:

给定A B(A>B)

情况1:每局初状态(A,B)都满足 A div B >1

               基本思想:尽量让自己去取每一局的初状态,让对手取每一局的末状态,则面临最后一局初状态就赢得胜利。

即每次取(A div B -1)*B,得到的新状态为(A mod B+B,B),对手没有选择,只能取B,保证下一局的初状态肯定由自己来取。

情况2:存在某局的初状态满足 (A div B)=1

            (  即:存在连续Pi~Pj局,其中i+1<j,  Ai div Bi>1, 且对于任意一局Pk,i<k<j,满足Ak div Bk=1.)

            如果j-i是偶数,则Pi和Pj初状态持有人相同,如果j-i是奇数,则可在Pi局将状态一次性取光,保证在Pj局中再一次拿到初状态。

综上,首先拿到A div B >1的人,总能根据两种情况做出正确的选择,从而在最后一局取得初状态,获得胜利。但如果最初开始每局都是A div B=1,则要根据局数来判断。

代码:

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int c;
    cin>>c;
    while(c--)
    {
        int m,n;
        cin>>m>>n;
        if(m<n)swap(m,n);
        int f=1;//表示Stan赢
        while(m/n==1&&m%n)//在一开始就是AdivB=1的情况
        {
            int t=m%n;
            m=n;
            n=t;
            f=-f;
        }
        if(f==1)cout<<"Stan wins"<<endl;
        else cout<<"Ollie wins"<<endl;
    }
    return 0;
}

             

猜你喜欢

转载自blog.csdn.net/sdau20171989/article/details/81267926
1.3