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 }
我就是我,颜色不一样的烟火 --- geloutingyu