1. 程式人生 > >POJ-2505 A multiplication game

POJ-2505 A multiplication game

題意: 給定一個數n (1 < n < 4294967295)從1開始, 可以乘以 【2, 9】中的任意一個數字, 最先乘法運算後最先大於等於n的那個人勝利。 分析: 博弈問題一般先找規律。 我們發現, 當n的範圍在【2, 9】之間時, Stan必勝, 因為Stan第一輪可以乘以【2, 9】中的任意一個數字。Stan的策略是使得他的每一步都能達到N狀態。那麼他的策略就是使得他的值儘可能快的到達n。 同理當n的範圍在 【10, 18】 之間時, Ollie必勝, 因為Ollie也可以乘以【2, 9】中的任意一個數字使得他的必勝範圍為【10, 2×9】。 Ollie的策略是使得他的每一步都達到P狀態, 那麼她的策略就是值儘可能最慢到達n。

根據以上分析, 我們可以得到: 【2, 9】 N狀態, Stan必勝 【9+1, 29】P狀態, Ollie必勝 【29 + 1, 299】N狀態, Stan必勝 【299 + 1, 299*2】 P狀態, Ollie必勝

所以我們可以根據上述的規律打表然後判斷n狀態出現的奇偶性。

程式碼如下:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;


//[2, 9] stan 
//[10, 2*9] ollie
//[2*9 + 1, 2*9*9] stan
//[2*9*9 + 1, 2*9*9*2] ollie

long long sg[] = {2, 9, 18, 162, 324, 2916, 5832, 52488, 104976, 944784, 1889568, 17006112, 34012224, 306110016, 612220032, 5509980288 };

int main () {
    long long n;
    while (cin >> n) {
        int cnt = 1;
        for (int i = 1; i < 17; i++) {
            if (sg[i] < n) {
                cnt++;
            } else {
                break;
            }
        }
        cout << (cnt % 2 ? "Stan" : "Ollie") << " wins." << endl;
    }
    
    return 0;
}