hdu1536(sg函数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1536

题意:首先输入K 表示一个集合的大小  之后输入集合 表示对于这对石子只能去这个集合中的元素的个数

之后输入 一个m 表示接下来对于这个集合要进行m次询问 

之后m行 每行输入一个n 表示有n个堆  每堆有n1个石子  问这一行所表示的状态是赢还是输 如果赢输入W否则L

思路:sg函数

一开始直接打表tle了,因该是多组输入的原因吧

然后我们再仔细考虑一下这个m,m<=100,一般来说,给的数据不可能每组的max(a[i]) (1<=i<=m)都达到1e4;

所以我们可以不必每次打表都打到1e4,我们可以通过dfs针对具体数据打表;这样就不会tle啦;

代码:

 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #define MAXN 200010
 5 using namespace std;
 6 
 7 int f[MAXN], sg[MAXN], n;
 8 
 9 int dfs_sg(int x){//sg函数
10     if(sg[x]!=-1){//之前已经计算过
11         return sg[x];
12     }
13     int vis[105];
14     memset(vis, 0, sizeof(vis));
15     for(int i=0; i<n; i++){//找到当前节点能到达的点
16         if(f[i]<=x){
17             dfs_sg(x-f[i]);
18             vis[sg[x-f[i]]]=1;
19         }
20     }
21     for(int i=0; ; i++){//求mex函数
22         if(!vis[i]){
23             sg[x]=i;
24             return sg[x];
25         }
26     }
27 }
28 
29 int main(void){
30     std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
31     while(cin >> n){
32         if(n==0){
33             break;
34         }
35         memset(sg, -1, sizeof(sg));
36         for(int i=0; i<n; i++){
37             cin >> f[i];
38         }
39         sort(f, f+n);
40         int k, t, x;
41         cin >> k;
42         while(k--){
43             cin >> t;
44             int ans=0;
45             for(int i=0; i<t; i++){
46                 cin >> x;
47                 ans^=dfs_sg(x);
48             }
49             if(ans==0){
50                 cout << "L";
51             }else{
52                 cout << "W";
53             }
54         }
55         cout << endl;
56     }
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/geloutingyu/p/6653734.html