POJ-2505 A multiplication game

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37753409/article/details/82837605

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必胜
【2
9 + 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;
}

猜你喜欢

转载自blog.csdn.net/qq_37753409/article/details/82837605