题目大意
解题思路
一、搜索解法:
此题仍然是零和博弈问题,但是由于数字范围太大,我们没有办法声明数组进行记忆化 搜索,尝试了直接进行深搜,但是发生了Runtime Error
,应该是深搜深度太深,超出了内存。
二、脑洞:
对一个状态,不妨假设
a
>
b
a>b
a>b.我们进行如下讨论:
- a % b = = 0 a\%b==0 a%b==0: 出口,则该状态为必胜态
- a − b < b a - b < b a−b<b:则只能先减去一个 b b b,进入下一状态。
-
a
−
b
>
b
a - b > b
a−b>b: 出口,该状态为必胜态。证明如下:
此时有 x > 1 , s . t . a − x b < b x > 1, s.t. a-xb<b x>1,s.t.a−xb<b ,我们对此状态进行讨论, 特别的,我们如果减去(x-1)b
:- 进入必败态,那么我们就进行 a − ( x − 1 ) b a-(x-1)b a−(x−1)b操作进入必败态,则该状态为必胜态.
- 进入必胜态,而此时有
a
′
−
b
<
b
a'-b<b
a′−b<b,因此下一状态为必败态。那么我们转而直接减去
xb
,直接进入必败态。所以该状态为必胜态。
代码
- dfs代码
#include<iostream>
using namespace std;
typedef long long ll;
bool dfs(ll a, ll b, int p)
{
if(a < b)
swap(a, b);
if(a % b == 0)
return p == 0;
ll n = a / b;
if(p == 0)
{
bool win = 0;
for(ll i=1; i<=n; i++)
{
if(dfs(a-i*b, b, 1-p))
{
win = 1;
break;
}
}
return win;
}
if(p == 1)
{
bool win = 1;
for(ll i=1; i<=n; i++)
{
if(dfs(a-i*b, b, 1-p)==0)
{
win = 0;
break;
}
}
return win;
}
}
int main()
{
ll a, b;
while(cin >> a >> b)
{
if(a == 0 && b == 0)
break;
if(dfs(a, b, 0))
cout << "Stan wins" << endl;
else
cout << "Ollie wins" << endl;
}
return 0;
}
- 脑洞代码
#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
ll a, b;
while(cin >> a >> b)
{
if(a == 0 && b == 0)
break;
int f=1;
while(true)
{
if(a < b)
swap(a, b);
if(a % b == 0)
break;
if(a - b > b)
break;
a -= b;
f = 1 - f;
}
if(f)
cout << "Stan wins" << endl;
else
cout << "Ollie wins" << endl;
}
return 0;
}