回 帖 发 新 帖 刷新版面

主题:ZOJ 1893 A Multiplication Game

            A multiplication game  

Stan and Ollie play the game of multiplication by multiplying an integer p by one of the numbers 2 to 9. Stan always starts with p = 1, does his multiplication, then Ollie multiplies the number, then Stan and so on. Before a game starts, they draw an integer 1 < n < 4294967295 and the winner is who first reaches pn. 

当输入为N时,如果Stan在能赢,则说明之前的一轮Ollie无论出多少都不能赢。设当乘积为M且该Ollie发难(设Ollie出p)时,Stan有必赢的策略(不管Ollie出什么,Stan都出9),即
    9×M<N,9×p×M≥N    (p≥2)
    等价于M≥ceil(N / (2×8))    (ceil为向上取整)
下面证明如果Stan在ceil(N/18)时有必赢的策略,则
    9×ceil(N/18)<N且18×ceil(N/18)≥N.
设N = 18×k + r (k≥1,0≤r<18)代人上式即得。
(在10到18之间,Ollie必赢,可手工验证。)

接着验证若Stan在ceil(N/18)时必输,则Stan在N时亦必输。只要Ollie出2,Stan即使出9也不能赢,Ollie接着出9,即赢。

# include <iostream>
# include <cmath>
using namespace std;

typedef unsigned long int ULI;
bool stanWin(ULI n)
{
    if (2 <= n && n <= 9) {
        return true;
    } else if (n < 2) {
        return false;
    } else {
        return stanWin(ceil(n / 18.0));
    }
}

int main()
{
    ULI n;
    while (cin >> n) {
        if (stanWin(n)) {
            cout << "Stan wins." << endl;
        } else {
            cout << "Ollie wins." << endl;
        }
    }
    return 0;
}

[url=http://blog.csdn.net/Sedgewick]感兴趣的来我的窝看看。[/url]

回复列表 (共1个回复)

沙发

一道相似的题目:pku acm 2348 Euclid's Game 
Description 
Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 0, and thereby wins. For example, the players may start with (25,7): 


         25 7
         11 7
          4 7
          4 3
          1 3
          1 0

an Stan wins. 

分析:                   (m, n)                 (m = k×n + r, k≥2, 0<r<n)
               /            |                   \
              /1            |2                   \k
    ((k-1)×n + r, n) ((k-2)×n + r, n) ……((k-k)×n + r, n)
       /
      /
((k-2)×n + r, n)……
可见其决策树具有相似性,如:
                         (25, 7)
                  /1        |2         \3
              (18, 7)    (11, 7)     (4, 7)
            /1       \2     |
        (11, 7)    (4, 7) (4, 7)
           |
        (4, 7)
           |
          ……
           |
        (1, 3)
可见,若 m / n ≥ 2,当前出牌者有必赢的策略。
下面证明若对手有多于一种的出牌选择,则不存在必输的情况。(以k = 2为例)
           Stan                  (m, n)            (m = kn + r,0 < r < n)
                              /1        \2
                        (n+r, n)     (r, n)
           Ollie            |
                        (r, n)
若(r,n)能赢,则Stan选择(n+r,n);反之,选择(r,n)。

而当m/n=1时,胜负取决于对手。故,
stanWins(m, n)
{
    ……
    if k = 1, then
        return ┐ollieWins(m - n, n)
    ……
}


# include <iostream>
using namespace std;

bool ollieWins(int m, int n);
bool stanWins(int m, int n)
{
    int maximum = (m > n ? m : n), minimum = (m < n ? m : n);
    int k = maximum / minimum, r = maximum % minimum;
    if (r == 0) {
        return true;
    } else if (k == 1) {
        return !ollieWins(maximum % minimum, minimum);
    } else {    // m / n > 1
        return true;
    }
}

bool ollieWins(int m, int n)
{
    int maximum = (m > n ? m : n), minimum = (m < n ? m : n);
    int k = maximum / minimum, r = maximum % minimum;
    if (r == 0) {
        return true;
    } else if (k == 1) {
        return !stanWins(maximum % minimum, minimum);
    } else {    // m / n > 1
        return true;
    }
}

int main()
{
    int m, n;
    while (cin >> m >> n) {
        if (m == 0 && n == 0) {
            break;
        }
        if (stanWins(m, n)) {
            cout << "Stan wins" << endl;
        } else {
            cout << "Ollie wins" << endl;
        }
    }
    return 0;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册