HDU 1536 & 1944

时间:2021-03-04 03:47:10

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[], vis[], s[], k; void getSG() {
sg[] = ;
for(int j = ; j <= ; j++) {
memset(vis, , sizeof(vis));
for(int i = ; i < k; i++) {
if(s[i] <= j) vis[sg[j-s[i]]] = ;
}
for(int i = ; ; i++) {
if(!vis[i]) {
sg[j] = i;
break;
}
}
}
} int main() {
while(~scanf("%d", &k), k) {
for(int i = ; i < k; i++)
scanf("%d", &s[i]);
getSG();
int m;
scanf("%d", &m);
while(m--) {
int l;
scanf("%d", &l);
int ans = ;
while(l--) {
int h;
scanf("%d", &h);
ans ^= sg[h];
}
if(!ans) putchar('L');
else putchar('W');
}
putchar('\n');
}
return ;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm> using namespace std; int sg[], vis[], s[], k; int getSG(int x) {
if(sg[x] != -) return sg[x];
memset(vis, , sizeof(vis));
for(int i = ; i < k; i++) {
if(s[i] <= x) {
getSG(x-s[i]);
vis[sg[x-s[i]]] = ;
}
}
for(int i = ; ; i++) {
if(!vis[i]) return sg[x] = i;
}
} int main() {
while(~scanf("%d", &k), k) {
for(int i = ; i < k; i++)
scanf("%d", &s[i]);
int m;
scanf("%d", &m);
memset(sg, -, sizeof(sg));
sg[] = ;
for(int i = ; i <= ; i++)
getSG(i);
while(m--) {
int l;
scanf("%d", &l);
int ans = ;
while(l--) {
int h;
scanf("%d", &h);
ans ^= sg[h];
}
if(!ans) putchar('L');
else putchar('W');
}
putchar('\n');
}
return ;
}

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

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm> using namespace std; int sg[], s[], k; void getSG() {
sg[] = ;
for(int j = ; j <= ; j++) {
set <int> S;
for(int i = ; i < k; i++) {
if(s[i] <= j) S.insert(sg[j-s[i]]);
}
int g = ;
while(S.count(g)) g++;
sg[j] = g;
}
} int main() {
while(~scanf("%d", &k), k) {
for(int i = ; i < k; i++)
scanf("%d", &s[i]);
getSG();
int m;
scanf("%d", &m);
while(m--) {
int l;
scanf("%d", &l);
int ans = ;
while(l--) {
int h;
scanf("%d", &h);
ans ^= sg[h];
}
if(!ans) putchar('L');
else putchar('W');
}
putchar('\n');
}
return ;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm> using namespace std; int sg[], s[], k; int getSG(int x) {
if(sg[x] != -) return sg[x];
set <int> S;
for(int i = ; i < k; i++) {
if(s[i] <= x) {
S.insert(getSG(x-s[i]));
}
}
int g = ;
while(S.count(g)) g++;
return sg[x] = g;
} int main() {
while(~scanf("%d", &k), k) {
for(int i = ; i < k; i++)
scanf("%d", &s[i]);
int m;
scanf("%d", &m);
memset(sg, -, sizeof(sg));
sg[] = ;
for(int i = ; i <= ; i++)
getSG(i);
while(m--) {
int l;
scanf("%d", &l);
int ans = ;
while(l--) {
int h;
scanf("%d", &h);
ans ^= sg[h];
}
if(!ans) putchar('L');
else putchar('W');
}
putchar('\n');
}
return ;
}