【洛谷1290】欧几里德的游戏(博弈论)

点此看题面

大致题意: 给定两个正整数,从 S t a n Stan Stan开始,每次将两个数中较大的数减去较小数的正整数倍(得到数不能小于0),然后是 O l l i e Ollie Ollie进行同样操作。若谁先得到0谁就胜利,请你求出谁会取得胜利。


分类讨论

这一看就是博弈论题。

我们可以用 w ( x , y ) w(x,y) w(x,y)来表示两个数分别为 x x x y y y时的获胜情况(设 x ≥ y x≥y xy),并设 a = ⌊ x y ⌋ , b = x a=\lfloor\frac xy\rfloor,b=x a=yx,b=x% y y y

下面是一波分类讨论:

  • 如果 x = y x=y x=y

    显然此时的决策者胜利(可以直接将 x x x减去 y y y,变成 ( y , 0 ) (y,0) (y,0))。

  • 如果 a ≥ 2 a≥2 a2

    • w ( y , b ) = 1 w(y,b)=1 w(y,b)=1

      则此时的决策者必然可以使当前状态转移到 ( y + b , b ) (y+b,b) (y+b,b)(只要将 x x x减去 y ( a − 1 ) y(a-1) y(a1)即可),然后对手就只能使状态转移到 ( y , b ) (y,b) (y,b),因此此时的决策者必胜。

    • w ( y , b ) = 0 w(y,b)=0 w(y,b)=0

      则此时的决策者必然可以使当前状态转移到 ( y , b ) (y,b) (y,b)(只要将 x x x减去 a y ay ay即可),则对手必输,因此此时的决策者必胜。

    综上所述,此时的决策者必胜。

  • 如果 a < 2 a<2 a<2

    这时,我们不能直接看出此时决策者是否必胜或必输,这时候就需要递归了,因为此时的决策只有一种(将 x x x减去 y y y),因此此时的获胜情况就是 ! w ( y , x − y ) !w(y,x-y) !w(y,xy)


递归函数w(x,y)

这样一来,就不难得出一个递归函数 w ( x , y ) w(x,y) w(x,y)了:

inline bool w(int x,int y)//递归函数,判断两个数分别为x和y,且x≥y时是否必胜
{
    if(x^y&&x/y<2) return !w(y,x-y);//如果x≠y且x/y<2,就不能直接看出必胜或必输,因此就执行此时唯一的决策方案,并递归调用w()函数
    return true;//否则,x=y或x/y≥2,通过上面的证明可得此时的决策者必胜
}

代码

#include
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?-(x):(x))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=ch:(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=ch))
#define N 20
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,m;
inline void read(int &x)
{
    x=0;static char ch;
    while(!isdigit(ch=tc()));
    while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline void ps(string x)
{
    register int i,len=x.length();
    for(i=0;i<len;++i) pc(x[i]);
}
inline bool w(int x,int y)//递归函数w(x,y)
{
    if(x^y&&x/y<2) return !w(y,x-y);
    return true;
}
int main()
{
    register int i,T;read(T);
    while(T--)
    {
        read(n),read(m);
        w(max(n,m),min(n,m))?ps("Stan wins\n"):ps("Ollie wins\n");
    }
    return fwrite(pp,1,pp_,stdout),0;
}

你可能感兴趣的:(洛谷,博弈论)