HDU 3595 GG and MM [Every-SG]
题意:
两个数$x,y$,一个人的决策为让大数减去小数的任意倍数(结果不能为负),出现0的人胜
一堆这样的游戏同时玩
Every-SG 游戏规定,对于还没有结束的单一游戏,游戏者必须对该游戏进行一步决策;
贪心:先手必胜的尽量长,先手必败的尽量短
对于Every-SG 游戏先手必胜当且仅当单一游戏中最大的step 为奇数。
$step(u) =$
\begin{cases}
0, & \text{$u为终止状态$}\\
max\{step(v)\}+1, & \text{ $sg(u)\neq 0\land v为u的后继\land sg(v)=0$ }\\
min\{step(v)\}+1, & \text{$sg(u)=0\land v为u的后继$}
\end{cases}
单个游戏,好熟悉啊,这不那个欧几里得游戏嘛
容易发现$a/b > 2$必胜,因为这时候掌握了主动权
然后$dfs$就好啦
$pair$还挺快的嘛
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define pii pair<int,int> #define MP make_pair #define fir first #define sec second typedef long long ll; const int N=1e3+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n; pii sg[N][N]; pii dfs(int a,int b){ if(a<b) swap(a,b); pii &now=sg[a][b]; if(now.fir!=0 || b==0) return now; int k=a/b;pii f=dfs(b,a%b); if(k==1) now=MP(f.fir^1,f.sec+1); else{ now=MP(1,f.sec+1); if(f.fir) now.sec++; } return now; } int main(){ freopen("in","r",stdin); while(scanf("%d",&n)!=EOF){ int mx=0; for(int i=1;i<=n;i++) mx=max( mx,dfs(read(),read()).sec ); if(mx&1) puts("MM"); else puts("GG"); } }
Copyright:http://www.cnblogs.com/candy99/