HDOJ 1525 Euclid's Game 博弈

题目大意是给定两个数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;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值