挑战程序设计竞赛: Eucid's Game

题目大意

在这里插入图片描述

解题思路

一、搜索解法:
此题仍然是零和博弈问题,但是由于数字范围太大,我们没有办法声明数组进行记忆化 搜索,尝试了直接进行深搜,但是发生了Runtime Error,应该是深搜深度太深,超出了内存。

二、脑洞:
对一个状态,不妨假设 a > b a>b a>b.我们进行如下讨论:

  • a % b = = 0 a\%b==0 a%b==0: 出口,则该状态为必胜态
  • a − b &lt; b a - b &lt; b ab<b:则只能先减去一个 b b b,进入下一状态。
  • a − b &gt; b a - b &gt; b ab>b: 出口,该状态为必胜态。证明如下:
    此时有 x &gt; 1 , s . t . a − x b &lt; b x &gt; 1, s.t. a-xb&lt;b x>1,s.t.axb<b ,我们对此状态进行讨论, 特别的,我们如果减去(x-1)b:
    • 进入必败态,那么我们就进行 a − ( x − 1 ) b a-(x-1)b a(x1)b操作进入必败态,则该状态为必胜态.
    • 进入必胜态,而此时有 a ′ − b &lt; b a&#x27;-b&lt;b ab<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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值