题目大意是给定两个数a,b,Stan always starts.规则是,每次只能把比较大的数减去比较小的数的整数倍,最后两个数中只要有一个数为0就结束,最后操作了的人为胜
首先:对于a,b中的比较大的数max和比较小的数min,不管两个人怎么取,一定会到达min,max % min的状态
因为max在没有减到比min小的时候,后续的操作依然是对max减去min的倍数,而一旦max比min小了,因为max = k*min + b,只有k=0的时候max才会比min小
依次类推直到其中一个数为0
那么他们必定在到达min,max%min的状态的时候总共减去了max / min个min;(这个时候很容易就可以想到利用gcd了)
利用gcd求出每次到达下一个状态需要减去的min的数量,存在stack中,那么问题就变成了对于排成一列的很多堆石子,要在第一堆石子中取出任意数量的石子,取完第一堆之后才能取第二堆(相当于在max,min没有到达min,max%min状态前不能对min,max%min进行操作),依次取完,最后取完所有石子的人获胜
因为是顺序取石子,可以利用dp
我的代码:
#include<stdio.h>
#include<string.h>
int stack[101], snum;
bool dp[101];
int Max(int a, int b)
{
return a > b ? a : b;
}
int gcd(int max, int min)
{
stack[++ snum] = max / min;
if(max % min == 0)
{
return min;
}
return gcd(min, max % min);
}
int main()
{
int a, b, max, min, i;
while(scanf("%d%d", &a, &b) != EOF && !(a == 0 && b == 0))
{
max = Max(a, b);
min = a + b - max;
if(max % min == 0)
{
printf("Stan wins\n");
continue;
}
snum = 0;
gcd(max, min);
dp[snum + 1] = 0;
for(i = snum; i >= 1; i --)
{
if(dp[i + 1] == 0 || dp[i + 1] == 1 && stack[i] > 1)
{
dp[i] = 1;
}
else
dp[i] = 0;
}
if(dp[1])
{
printf("Stan wins\n");
}
else
printf("Ollie wins\n");
}
return 0;
}