【P1290】 欧几里得游戏

欧几里德的两个后代 Stan 和 Ollie 正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的。给定两个正整数 M 和 N,从 Stan 开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数不能小于 0。然后是 Ollie,对刚才得到的数,和 M,N 中较小的那个数,再进行同样的操作……直到一个人得到了 0,他就取得了胜利。下面是他们用 (25,7) 两个数游戏的过程:

Start:(25,7)

Stan:(11,7)

Ollie:(4,7)

Stan:(4,3)

Ollie:(1,3)

Stan:(1,0)

Stan 赢得了游戏的胜利。

现在,假设他们完美地操作,谁会取得胜利呢?
输入格式

本题有多组测试数据。

第一行为测试数据的组数 C。 下面 C 行,每行为一组数据,包含两个正整数 M,N(M,N<2^31)。
输出格式

对每组输入数据输出一行,如果 Stan 胜利,则输出 Stan wins;否则输出 Ollie wins。
输入 :
2
25 7
24 15

输出:
Stan wins
Ollie wins
这是博弈论和欧几里得算法的结合,这道题我刚开始自己没有想出思路,感觉这种类型的题目第一次做,所以记在这里。

对于当前的两个数m,n(假设m始终为大数),如果m是n的倍数,那么当前的这个人肯定是可以得到0,也就是他稳赢。
如果m=K*n+z,(k>=2)那么当前的人可以得到(n+z,n)和(n,z)这两种情况,因为是两个人之间的互相博弈,所以这个人可以自己决定得到哪种情况,那么必赢的情况肯定是这两者之一,所以此时当前人也是稳赢。
如果k=1,那么当前的这个人只能得到(n,z)这种情况,此时就要拿n,z再去递归去看后面的胜负所定了。
AC代码附上:

#include <iostream>
using namespace std;
int gmd(int m, int n,int flag)
{
	if (m % n == 0)
		return flag;
	if (m / n >= 2)
		return flag;
	else
	{
     return gmd(n, m - n,++flag);
	}
}
int main()
{
	int t; 
	cin >> t;
	int m, n,k,flag;
	while (t--)
	{
		cin >> m >> n;
		flag=1;
		if (m < n)
		{
			int temp;
			temp = m;
			m = n;
			n = temp;
		}
		k = gmd(m, n,flag);
		if (k % 2 == 1)
			cout << "Stan wins" << endl;
		else
			cout << "Ollie wins" << endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值