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;
}


猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80726435