> 文章列表 > HDU3595 GG and MM

HDU3595 GG and MM

HDU3595 GG and MM

题目大意

MMMMMMGGGGGG玩游戏,每轮游戏有两堆石子,玩家每次操作需要任选一个正整数kkk,并从石子数量较多的一堆石子中取出石子数量较少的一堆石子的石子数量的kkk倍的石子。令石子数量较少的一堆石子有xxx个石子,石子数量较多的一堆石子有yyy个石子,则让y=y−k×xy=y-k\\times xy=yk×x。无法操作者输。nnn次游戏同时进行,每次每个玩家在未完成的各个游戏中进行操作,以最后结束的一轮游戏的胜负来决定最终的胜负。

MMMMMM先手。如果MMMMMM有必胜策略,则输出MMMMMM;否则输出GGGGGG

有多组数据。

数据范围

1≤t≤1001\\leq t\\leq 1001t100ttt为数据组数。

1≤n≤1000,1≤p,q≤10001\\leq n\\leq 1000,1\\leq p,q\\leq 10001n1000,1p,q1000

题解

有一道类似的题:HDU1525 Euclid‘s Game

设这两堆石子的数量为n,mn,mn,mn≥mn\\geq mnm,我们需要分讨论

  • 如果n%m==0n\\% m==0n%m==0,则(n,m)(n,m)(n,m)是先手必胜态
  • 如果n>2mn>2mn>2m,则(n,m)(n,m)(n,m)一定是先手必胜态,因为
    • 如果(n%m,m)(n\\%m,m)(n%m,m)为先手必败态,则因为(n,m)(n,m)(n,m)可以转到(n%m,n)(n\\%m,n)(n%m,n),所以(n,m)(n,m)(n,m)为先手必胜态
    • 如果(n%m,m)(n\\%m,m)(n%m,m)为先手必胜态,则因为(n%m+m,m)(n\\%m+m,m)(n%m+m,m)只能到达(n%m,m)(n\\%m,m)(n%m,m),所以(n%m+m,m)(n\\%m+m,m)(n%m+m,m)为先手必败态,又因为(n,m)(n,m)(n,m)可以到达(n%m+m,m)(n\\%m+m,m)(n%m+m,m),所以(n,m)(n,m)(n,m)为先手必胜态
  • 如果m≤n<2mm\\leq n<2mmn<2m,则(n,m)(n,m)(n,m)只能转到(n−m,m)(n-m,m)(nm,m),可以根据(n−m,m)(n-m,m)(nm,m)的状态来判断(n,m)(n,m)(n,m)的状态,重复上述操作即可

显然,对于一轮游戏,如果一方有必胜策略,则其必胜策略所需的步数是一定的。所以,我们只需要求出每轮游戏需要的步数,求最大值,根据步数最大的那一轮的胜负情况,来推出最终的胜负情况。

code

#include<bits/stdc++.h>
using namespace std;
int n,vt,v1,v2;
int gt(int x,int y){if(x<y) swap(x,y);if(!y) return 0;if(!gt(y,x%y)){++vt;return 1;}if(x>2*y){vt+=2;return 1;}++vt;return 0;
}
int main()
{while(scanf("%d",&n)!=EOF){v1=v2=0;for(int i=1,x,y;i<=n;i++){scanf("%d%d",&x,&y);vt=0;if(gt(x,y)) v1=max(v1,vt);else v2=max(v2,vt);}if(v1>v2) printf("MM\\n");else printf("GG\\n");}return 0;
}