2020NYIST个人积分赛第二场-A

题面

疫情当下,有两个很无聊的人,小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<2
n 因为取法只有依次取所以我们就依次取。

也就是说,当存在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必胜

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值