• Bzoj 4147: [AMPPZ2014]Euclidean Nim(博弈)


    4147: [AMPPZ2014]Euclidean Nim
    Time Limit: 1 Sec Memory Limit: 256 MB
    Description
    Euclid和Pythagoras在玩取石子游戏,一开始有n颗石子。
    Euclid为先手,他们按如下规则轮流操作:
    ·若为Euclid操作,如果n< p,则他只能新放入p颗石子,否则他可以拿走p的倍数颗石子。
    ·若为Pythagoras操作,如果n< q,则他只能新放入q颗石子,否则他可以拿走q的倍数颗石子。
    拿光所有石子者胜利。假设他们都以最优策略操作,那么获胜者是谁?
    Input
    第一行包含一个正整数t(1<=t<=1000),表示数据组数。
    接下来t行,每行三个正整数p,q,n(1<=p,q,n<=10^9),表示一组数据。
    Output
    输出t行。第i行输出第i组数据的答案,如果Euclid必胜,输出E,如果Pythagoras必胜,输出P,
    如果游戏永远不会停止,输出R。
    Sample Input
    4
    3 2 1
    2 3 1
    3 4 5
    2 4 3
    Sample Output
    P
    P
    E
    R
    HINT
    在第一组数据中,Euclid必须新放入3颗石子,然后Pythagoras拿走4颗石子并获胜。
    Source
    鸣谢Claris上传

    /*
    博弈题.
      首先令d=gcd(p,q),如果d不整除n,由扩展欧几里得显然无解。
      有解的情况:
      ① p=q :显然先手必胜。 
      ② p>q&&n<p :先手第一次数量加p,后手可以把数量变成n%q,这样先手永远无法取石子,后手必胜。 
      ③ p>q&&n>=p :如果先手第一次取完石子,石子数量大于p,后手还是可以把数量变成n%q,后手必胜;
           否则,先手取成n mod p -> 后手+q -> 先手?p -> 后手+q -> ……,如果n%(p-q)=0,则先手必胜。
      ④ p<q&&n<p :先手第一次把数量变成n+p,如果n+p<q,就变成了第二种情况,否则是第三种情况。
      ⑤ p<q&&n>=p :那么先手可以把石子变成n%p,就变成了第二种情况。 
    粘的zjk的2333. 
    */
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int t,n,p,q;
    int gcd(int x,int y)
    {
        if(!y) return x;
        return gcd(y,x%y);
    }
    bool check(int a,int b,int x)
    {
        if(x%a<b&&(x%a)%(a-b)==0) return true;
        return false;
    }
    void slove()
    {
        int g=gcd(p,q);
        if(n%g){printf("R
    ");return ;}//1 
        p/=g,q/=g,n/=g;
        if(p==q) {printf("E
    ");return ;}//2
        if(p>q&&n<p) {printf("P
    ");return;}//3
        if(p>q&&n>=p)//4
        {
            if(check(p,q,n)) {printf("E
    ");return ;}
            else {printf("P
    ");return ;}
        }
        if(p<q&&n<p)//5
        {
            if(n+p<q) {printf("E
    ");return ;}
            else if(check(q,p,n+p)) {printf("P
    ");return ;}
            else  {printf("E
    ");return ;}
        }
        if(p<q&&n>=p)  {printf("E
    ");return ;}//6
        return ;
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&p,&q,&n);
            slove();
        }
        return 0;
    }
  • 相关阅读:
    关于键保留表的一些汇总
    pl/sql,Oracle数据库中,不小心delete数据并提交后如何恢复被删数据
    创建视图的with check option选项。
    oracle中update,insert,delete的高级用法
    物化视图详解--介绍、创建方法、例子
    Oracle 视图备忘
    利用替换变量提高Oracle交互性(define)
    Sqlplus中的VARIABLE以及使用VARIABLE之后使用execute。
    Unity3d 引擎原理详细介绍
    Unity 3D主要特性和缺陷
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068026.html
Copyright © 2020-2023  润新知