P1290 【欧几里德的游戏】

P1290 【欧几里德的游戏】

真·做题全凭感性


从题目中很容易看出

这是一道\(Gcd\)的题

同时又结合了一些略略的博弈论(丢下锅跑真爽

我们看,辗转相减的\(a,b\)一共只有两种情况

  • \(a-b<b,a>b\),就是\(a\)\(b\)大,但是比$b \(的两倍小,这种情况时。我们的\)S\(和\)O$君就只能硬着头皮去减了。

  • \(a>2b\),就是a比b的二倍大。这时候我们的\(S\)\(O\)君就需要ta们的大脑进行一波用命分析-1s,-1s

  • PS:a b是变量

因为\(a>2b\),所以我们的\(S\)\(O\)君就可以有两种选择

  1. 将a减成小于b,就是进行辗转相除的过程。

  2. 让位,就是在正常进行游戏的前提下,将现在的状态转移给对手(a>b or a < b)。

  3. 通过上面两种骚操作,他肯定就能赢了。

到此,我们就大体分析van了。

另外因为是\(S\)\(O\)君都是极其聪明的(-1s,-1s,用命分析)

所以我们可以看做他们是已经知道自己做出选择后的结果的。

上代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
bool dfs(int a,int b,int who)
{
	if(b==0)//van的游戏结束
		return false;//当前人fail
	if(a/b==1)//第一种情况,只能硬着头皮上
		return !dfs(b,a-b,who^1);
	if(a/b>1)
	{
		/*if(dfs(b,a%b,who^1))//如果我们将a变成小于b的情况,然后对手赢了,我们就可以改命
			return true;//改命
		else
			return true;//如果对手输了,那是更好不过了
		ps:我这里写的有些不大严谨233*/
		return true;//上面的返回都是true
        //至于为什么可以怎么写,一方面是我们利用上面的归纳法总结出来的233
        //也可以这么想,拿到这种情况的人,是可以可以控制a,b的大小的。
        //也就是控制了游戏局数,就像你买了一个5000~6000的挂,神仙一样,为所欲为。(逃
	}
}
int main()
{
	int k;
	scanf("%d",&k);
	int a,b;
	while(k--)
	{
		scanf("%d%d",&a,&b);
		if(a<b)
			swap(a,b);//保证a>b
		if(dfs(a,b,1))//简单的判断,第三个参数其实没有的,只是我调试用的。
			printf("Stan wins\n");
		else
			printf("Ollie wins\n");
	}
}
posted @ 2018-06-05 16:25  Lance1ot  阅读(144)  评论(0编辑  收藏  举报