1 条题解

  • 0

    题意分析:

    给定两个数,两个人每次从较大数中减去较小数的倍数,谁先得到00谁获胜,为谁赢?

    解题思路:

    这个问题类似于“辗转相除法”的过程,但加入了博弈论的最优策略选择。关键观察点: 如果较大的数是较小数的倍数,当前玩家可以直接获胜(因为可以直接减去整个数得到00)。 否则,当前玩家可以控制游戏走向必败态,让对手处于不利局面。

    实现步骤:

    令一种可能出现的整数对为(a,b)(a,b),其中(b>a)(b>a)。有两种情况ba<ab−a<a,只能从bb中减去一个aa,得到状态(ba,a)(b−a,a),那么如果(ba,a)(b−a,a)是必胜态的话,(ab)(a,b)就是必败态,反之同理。ba>ab−a>a,可以从bb中减去至少22aa,假设可以从bb中最多可以减去xxaa,那么从bb中减去(x1)(x−1)aa后得到状态(a,b(x1)a)(a,b−(x−1)∗a),此时即为讨论的第一种情况。如果状态(ab(x1)a)(a,b−(x−1)∗a)为必败态的话,那么(a,b)(a,b)就是必胜态,如果状态(a,b(x1)a)(a,b−(x−1)∗a)为必胜态的话,那么(bxa,a)(b−x∗a,a)肯定是必败态,所以直接减去xx倍的aa,得到必败态,那么(a,b)(a,b)即为必胜态。

    C++ 实现

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    bool canWin(int a, int b, bool isStanTurn) {
        if (b == 0) return false; // 上一步已经赢了,当前玩家无法操作
        if (a / b >= 2) return isStanTurn; // 可以一步获胜
        return !canWin(b, a % b, !isStanTurn); // 否则进入下一状态
    }
    
    int main() {
        int a, b;
        while (cin >> a >> b) {
            if (a == 0 && b == 0) break;
            
            bool stanWins;
            if (a < b) swap(a, b); // 确保 a >= b
            
            if (a == b) {
                stanWins = true; // 可以直接减去 b,Stan 直接获胜
            } else {
                stanWins = canWin(a, b, true);
            }
            
            cout << (stanWins ? "Stan wins" : "Ollie wins") << endl;
        }
        return 0;
    }
    
    
    
    
    • 1

    信息

    ID
    1349
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    1
    上传者