http://acm.hdu.edu.cn/showproblem.php?pid=1848

利用计算grundy数组,把一类博弈转化为nim博弈,最后x不为0为先手必胜态

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std ;

//N堆硬币,每堆Xi
//每次从一堆中取a1 a2...ak,先取完胜 

const int MAX_X=1005;
const int MAX_K=25;
const int MAX_N=5;

int N, K, X[MAX_N], A[MAX_K];

int grundy[MAX_X]; 

void solveSG() {
    grundy[0] = 0;
    //int max_x = *max_element(X, X + N);
    for(int j = 1; j <= 1000; j++) {
        set <int> s;
        for(int i = 0; i < 20; i++){  //A[i] <= j
            if(A[i] <= j) s.insert(grundy[j-A[i]]);
        }
        int g = 0;
        while(s.count(g)) g++;
        grundy[j] = g;
    }
    /*
    int x = 0;
    for(int i = 0; i < N; i++) x ^= grundy[X[i]];
    if(x) puts("Fibo");//先手胜
    else puts("Nacci");//后手胜 
    */
} 

int main() {
    A[0] = A[1] = 1;
    for(int i = 2; i < 20; i++)
        A[i] = A[i-1] + A[i-2];
    solveSG();
    while(~scanf("%d%d%d", &X[0], &X[1], &X[2])) {
        if(!X[0] && !X[1] && !X[2]) break;
        int x = 0;
        for(int i = 0; i < 3; i++) x ^= grundy[X[i]];
        if(x) puts("Fibo");//先手胜
        else puts("Nacci");//后手胜 
    }
    return 0;
}
View Code