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

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

一样的题

题意:先给一个集合,代表可能发生的转移。然后m个询问,可以理解为每次给l堆石子,每堆有hi个,问博弈策略

直接用sg定理,非常简单,转移给的清清楚楚,照着写就行,递推或者记忆化搜索都行。

这题的时间卡的紧,开始死活过不了,看别人代码把vis数组开成100就过了(原来开的1w),深感此题有问题,sg的值最大应该1w才对(或者我想错了欢迎指出?)

AC 代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

using namespace std;

int sg[10005], vis[105], s[105], k;

void getSG() {
    sg[0] = 0;
    for(int j = 1; j <= 10000; j++) {
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < k; i++) {
            if(s[i] <= j) vis[sg[j-s[i]]] = 1;
        }
        for(int i = 0; ; i++) {
            if(!vis[i]) {
                sg[j] = i;
                break;
            }
        }
    }
}

int main() {
    while(~scanf("%d", &k), k) {
        for(int i = 0; i < k; i++)
            scanf("%d", &s[i]);
        getSG();
        int m;
        scanf("%d", &m);
        while(m--) {
            int l;
            scanf("%d", &l);
            int ans = 0;
            while(l--) {
                int h;
                scanf("%d", &h);
                ans ^= sg[h];
            }
            if(!ans) putchar('L');
            else putchar('W');
        }
        putchar('\n');
    }
    return 0;
} 
View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

using namespace std;

int sg[10005], vis[105], s[105], k;

int getSG(int x) {
    if(sg[x] != -1) return sg[x]; 
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < k; i++) {
        if(s[i] <= x) {
            getSG(x-s[i]);
            vis[sg[x-s[i]]] = 1;
        }
    }
    for(int i = 0; ; i++) {
        if(!vis[i]) return sg[x] = i;
    }
}

int main() {
    while(~scanf("%d", &k), k) {
        for(int i = 0; i < k; i++)
            scanf("%d", &s[i]);
        int m;
        scanf("%d", &m);
        memset(sg, -1, sizeof(sg));
        sg[0] = 0;
        for(int i = 0; i <= 10000; i++)
            getSG(i);
        while(m--) {
            int l;
            scanf("%d", &l);
            int ans = 0;
            while(l--) {
                int h;
                scanf("%d", &h);
                ans ^= sg[h];
            }
            if(!ans) putchar('L');
            else putchar('W');
        }
        putchar('\n');
    }
    return 0;
} 
View Code

超时代码(但感觉非常正确,不知道被卡在哪里)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

using namespace std;

int sg[10005], s[105], k;

void getSG() {
    sg[0] = 0;
    for(int j = 1; j <= 10000; j++) {
        set <int> S;
        for(int i = 0; i < k; i++) {
            if(s[i] <= j) S.insert(sg[j-s[i]]);
        }
        int g = 0;
        while(S.count(g)) g++;
        sg[j] = g; 
    }
}

int main() {
    while(~scanf("%d", &k), k) {
        for(int i = 0; i < k; i++)
            scanf("%d", &s[i]);
        getSG();
        int m;
        scanf("%d", &m);
        while(m--) {
            int l;
            scanf("%d", &l);
            int ans = 0;
            while(l--) {
                int h;
                scanf("%d", &h);
                ans ^= sg[h];
            }
            if(!ans) putchar('L');
            else putchar('W');
        }
        putchar('\n');
    }
    return 0;
} 
View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

using namespace std;

int sg[10005], s[105], k;

int getSG(int x) {
    if(sg[x] != -1) return sg[x]; 
    set <int> S;
    for(int i = 0; i < k; i++) {
        if(s[i] <= x) {
            S.insert(getSG(x-s[i]));
        }
    }
    int g = 0;
    while(S.count(g)) g++;
    return sg[x] = g;
}

int main() {
    while(~scanf("%d", &k), k) {
        for(int i = 0; i < k; i++)
            scanf("%d", &s[i]);
        int m;
        scanf("%d", &m);
        memset(sg, -1, sizeof(sg));
        sg[0] = 0;
        for(int i = 0; i <= 10000; i++)
            getSG(i);
        while(m--) {
            int l;
            scanf("%d", &l);
            int ans = 0;
            while(l--) {
                int h;
                scanf("%d", &h);
                ans ^= sg[h];
            }
            if(!ans) putchar('L');
            else putchar('W');
        }
        putchar('\n');
    }
    return 0;
} 
View Code