题面
疫情当下,有两个很无聊的人,小A和小B,准备玩一个游戏,玩法是这样的,从两个自然数开始比赛。第一个玩家小A从两个数字中的较大者减去两个数字中较小者的任何正倍数,前提是得到的数字必须是非负的。然后,第二个玩家小B对得到的两个数字做同样的处理,两个玩家交替进行,直到一个玩家能够从大的数字中减去较小数字的倍数,达到0,从而获胜。例如,玩家可以从(25,7)开始 :
25 7
A 11 7
B 4 7
A 4 3
B 1 3
A 1 0
这是个 小A 获胜的例子.
Input
多组输入,不超过6组。每行为一组数据,包含两个正整数M,N(M,N<2^31)。
Output
对于每一行输入,输出一行,若小A获胜,那么输出“Stan wins”否则输出“Ollie wins”。假设这两个玩家都玩得很好。最后一行输入包含两个零,不应进行处理。
Sample Input
34 12
15 24
0 0
Sample Output
Stan wins
Ollie wins
思路
博弈:欧几里得的游戏
1.假设m>n,若m是n的整数倍,即m%n=0时小A必胜。
2.如果m>2n时,则可能存在两种状态:
举个栗子:m=38 n=9
第一种取法
A 38中取4个9
B 去取9和2
…
第二种取法
A 38中取3个9
B 11中取1个9
A 去取9和2
…
可以看出通过这个取法A就掌握了主动权,A就可以控制局势。
因为两个玩家足够聪明,每个玩家肯定会用对自己最有利的取法,所以出现这种状态时,先手(小A)必胜。
3.如果m>0&&m<2n 因为取法只有依次取所以我们就依次取。
也就是说,当存在maxx>=2*minn时,就会出现小A(stan)必胜的结果,若不存在,就通过循环判断知道结束进行了几轮游戏,如果是奇数次为小B(ollie)获胜,反之小A(stan)获胜。
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
int a, b, flag, c, maxx, minn;
while (scanf("%d%d",&a,&b)!=EOF)
{
if (a == 0 && b == 0)
break;
flag = 0;
maxx = max(a, b);
minn = min(a, b);
while(minn>0)
{
c=maxx%minn;
if(c==0||maxx>2*minn)
break;
maxx=minn;
minn=c;
flag++;
}
if (flag % 2 == 1)
printf("Ollie wins\n");
else
printf("Stan wins\n");
}
}
以上为自己见解。。。
另附大佬的见解:
当m>2*n时,若为A的回合,则一定可以取成m%n + n ,那么下回合 (m%n + n,n),此时n小,则下回合取的人只能取为(m%n,n),那么下回合就必胜。经历了两回合,所以还是A必胜