POJ2348 Euclid's Game(博弈&自由度)

Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 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.
Input
The input consists of a number of lines. Each line contains two positive integers giving the starting two numbers of the game. Stan always starts.
Output
For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly. The last line of input contains two zeroes and should not be processed.
Sample Input
34 12
15 24
0 0
Sample Output
Stan wins
Ollie wins

题意:

让我们看一下这个以辗转相除法为基础的游戏。

给定两个整数a和b。Stan和Ollie轮流从较大的数字中减去较小数字的倍数。这里的倍数指的是1倍、2倍等这样的正整数倍,并且相减后的结果不能小于零。Stan先手,在自己的回合将其中一个数变为零的一方获胜。当双方都采取最优策略时,谁会获胜?


解题思路:

让我们来找找看该问题中必胜态和必败态的规律。首先,如果a>b则交换,假设a<b。另外,如果b已经是a的倍数了则必胜,所以假设b并非a的倍数。此时,a和b的关系,按自由度的观点,可以分成以下两类。

(1)b-a<a的情况

(2)b-a>a的情况

对于第一种情况,如果从b中减去a的2倍以上的数则变为负数,所以只能从b中减去a,没有选择的余地。相对的,对于第二种情况,有从b中减去a,减去2a,或更高的倍数等多种选择。

对于第一种情况,要判断必胜还是必败是很简单的。因为没有选择的余地,如果b减去a之后所得到的状态是必败态的话,它就是必胜态,如果得到的是必胜态的话,它就是必败态。

例如,从(4,7)这个状态出发就完全没有选择的机会,按照

(4,7)-->(4,3)-->(1,3)

的顺序,轮到(1,3)的一方将获胜, 所以有

(4,7)-->(4,3)-->(1,3)

必胜-->必败-->必胜

可见(4,7)是必胜态。


接下来,我们来看一下第二种情况是必胜态还是必败态。假设x是使得b-ax<a的整数,考虑一下从b中减去a(x-1)的情况。例如对于(4,19)则减去12。

此时,接下来的状态就成了前边讲过的没有选择余地的第一种情况。如果该状态是必败态的话,当前状态就是必胜态。

那么,如果减去a(x-1)后的状态是必胜态的话,该如何是好呢?此时,从b中减去ax后的状态是减去a(x-1)后的状态唯一可以转移到的状态,根据假设,减去a(x-1)后的状态是必胜态,所以该状态是必败态。因此,当前状态是必胜态。

例如对于(4,17),由于从17中减去12得到的(4,5)就是必败态,所以只要减去12就能获胜。另一方面,对于(4,19),减去12得到的(4,7)是必胜态,因此(4,3)就是必败态,只要减去16就能获胜。

由此可知,第二种情况总是必胜的。所以,从初始状态开始,最先到达有自由度的第二种状态的一方必胜。


AC代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
	int a,b;
	while(~scanf("%d%d",&a,&b)&&a&&b)
	{
		bool f=true;
		for(;;)
		{
			if(a>b) swap(a,b);
			if(b%a==0) break;//b是a的倍数时必胜 
			if(b-a>a) break;//如果是第二种情况必胜 
			b-=a;
			f=!f;
		}
		if(f) printf("Stan wins\n");
		else printf("Ollie wins\n");
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值