25 7 11 7 4 7 4 3 1 3 1 0
an Stan wins.
34 12 15 24 0 0Sample 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;
}