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\)君就可以有两种选择
-
将a减成小于b,就是进行辗转相除的过程。
-
让位,就是在正常进行游戏的前提下,将现在的状态转移给对手(a>b or a < b)。
-
通过上面两种骚操作,他肯定就能赢了。
到此,我们就大体分析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");
}
}