NOI 4.2 数论 1350:Euclid's Game

题目来源:http://noi.openjudge.cn/ch0402/1350/

1350: Euclid's Game

总时间限制 1000ms  内存限制 65536kB

描述

Two players, Stan and Ollie, play, starting with two naturalnumbers. Stan, the first player, subtracts any positive multiple of the lesserof the two numbers from the greater of the two numbers, provided that theresulting number must be nonnegative. Then Ollie, the second player, does thesame with the two resulting numbers, then Stan, etc., alternately, until oneplayer is able to subtract a multiple of the lesser number from the greater toreach 0, and thereby wins. For example, the players may start with (25,7): 

         25 7
         11 7
          4 7
          4 3
          1 3
          1 0


an Stan wins.

输入

The input consists of a number of lines. Each line contains twopositive integers giving the starting two numbers of the game. Stan always starts.

输出

For each line of input, output one line saying either Stan winsor Ollie wins assuming that both of them play perfectly. The last line of inputcontains two zeroes and should not be processed.

样例输入

34 12
15 24
0 0

样例输出

Stan wins
Ollie wins

来源

Waterloo local 2002.09.28

-----------------------------------------------------

思路

【题意】

Stan和Ollie用两个整数a,b做游戏,Stan先手。两人轮流把两个数中较大者减去较小者的一个正整数倍,且使得结果仍是非负数。如此进行下去,直到某人操作过后出现一个0,则该人获胜。现给出a,b,问谁有必胜策略。

【思路】

不妨设每轮中a是较大者。对每轮操作,都可以分3种情况讨论:

1. a % b == 0, 先手必胜

2. a > 2*b, 此时先手至少有(a%b, b)和(a%b+b, b)两种操作的选择。注意到(a%b+b, b)再经过一次操作可以得到(a%b, b),故(a%b, b)和(a%b+b, b)分别对应两个人的必胜情况。此时先手可以从中选一个属于自己的必胜情况,因此一旦出现a > 2*b,先手必胜

3. b < a < 2*b, 此时先手只有一种选择: (a-b, b). 对(a-b, b)重复该讨论

故出现情况1和情况2时可以直接判断是先手胜,出现情况3则循环直到出现情况1或情况2再判断。

【坑点】

一定要long long! 不用long long 用int只有5分!ZOJ上也是这样,只有HDU上用int可以AC.

-----------------------------------------------------

代码

#include<iostream>
using namespace std;

void swap (long long &a, long long &b)					// 把a变为ab较大者,b变为ab较小者
{
	int aa,bb;
	aa = max(a,b);
	bb = min(a,b);
	a = aa;
	b = bb;
}


int main()
{
	long long a,b;
	bool flag;
	while (cin >> a >> b)
	{
		if (a==0 && b==0)
		{
			break;
		}
		flag = true;
		swap(a,b);
		if (a%b==0)
		{
			cout << "Stan wins" << endl;
			continue;
		}
		while (a>b && a<2*b)
		{
			a = a-b;
			swap(a,b);
			flag = !flag;
		}
		if (flag)
		{
			cout << "Stan wins" << endl;
		}
		else
		{
			cout << "Ollie wins" << endl;
		}
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值