当前位置: 代码迷 >> 综合 >> bzoj 4147: [AMPPZ2014]Euclidean Nim
  详细解决方案

bzoj 4147: [AMPPZ2014]Euclidean Nim

热度:48   发布时间:2023-10-29 05:58:53.0

题意

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

题解

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