bzoj 4147: [AMPPZ2014]Euclidean Nim

版权声明:本文为博主原创文章,爱转载的表明出处就好. https://blog.csdn.net/qq_36797743/article/details/81214667

题意

Euclid和Pythagoras在玩取石子游戏,一开始有n颗石子。
Euclid为先手,他们按如下规则轮流操作:
若为Euclid操作,如果n < p,则他只能新放入p颗石子,否则他可以拿走p的倍数颗石子。
若为Pythagoras操作,如果n < q,则他只能新放入q颗石子,否则他可以拿走q的倍数颗石子。
拿光所有石子者胜利。假设他们都以最优策略操作,那么获胜者是谁?

题解

首先,肯定是一直加(其实只会加一轮),知道有人可以动为止,这个人为新的p,另外一个人为新的q
我们考虑,如果 p = q ,那么直接判就好了
否则,我们考虑,如果 p < q ,那么我们考虑,如果是有人可以赢的,那么先手肯定是一直取p,后手不能动,这样先手是必胜的
否则,则是 p > q ,这时候先手也不可以给后手动,否则就转化为上一种情况,他就GG了
所以先手能做的只有一直把 n % p ,尽量让后手不能动
如果存在一个时刻 n % p = 0 ,那么先手就赢了
否则,如果有一个时候后手开始动,那么就是第二种情况了

CODE:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int T;
int p,q,n;
int gcd (int a,int b)   {return a==0?b:gcd(b%a,a);}
int ans;
void solve (int n,int p,int q,int now)
{
    //printf("YES:%d %d %d %d\n",n,p,q,now);
    if (p<q)//先手一直拿就可以了 
    {
        n=n%p;
        int t=p-n,d=gcd(p,q);
        if (t%d==0) ans=now;
    }
    else//先手一直拿 
    {
        n=n%p+q;//第一轮过后
        int t=p-q;//每一次会少这么多
        if ((n-p)%t==0)
        {
            ans=now;
            return ;
        }
        int d=(n-p)/t;
        d++;
        n=n-d*t;
        n=n%q;
        t=q-n;
        d=gcd(p,q);
        if (t%d==0) ans=3-now;
    }
}
int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d",&p,&q,&n);
        ans=0;
        if (p==q)
        {
            if (n%p==0) ans=1;
        }
        else
        {
            if (n<p)
            {
                n=n+p;
                if (n<q)
                {
                    n=n+q;
                    solve(n,p,q,1);
                }
                else solve(n,q,p,2);
            }
            else solve(n,p,q,1);
        }
        if (ans==0) printf("R\n");
        if (ans==1) printf("E\n");
        if (ans==2) printf("P\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36797743/article/details/81214667