S-Nim
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1536
Problem Description
Arthur and his sister Caroll have been playing a game called Nim for some time now. Nim is played as follows:
The starting position has a number of heaps, all containing some, not necessarily equal, number of beads.
The players take turns chosing a heap and removing a positive number of beads from it.
The first player not able to make a move, loses.
Arthur and Caroll really enjoyed playing this simple game until they recently learned an easy way to always be able to find the best move:
Xor the number of beads in the heaps in the current position (i.e. if we have 2, 4 and 7 the xor-sum will be 1 as 2 xor 4 xor 7 = 1).
If the xor-sum is 0, too bad, you will lose.
Otherwise, move such that the xor-sum becomes 0. This is always possible.
It is quite easy to convince oneself that this works. Consider these facts:
The player that takes the last bead wins.
After the winning player's last move the xor-sum will be 0.
The xor-sum will change after every move.
Which means that if you make sure that the xor-sum always is 0 when you have made your move, your opponent will never be able to win, and, thus, you will win.
Understandibly it is no fun to play a game when both players know how to play perfectly (ignorance is bliss). Fourtunately, Arthur and Caroll soon came up with a similar game, S-Nim, that seemed to solve this problem. Each player is now only allowed to remove a number of beads in some predefined set S, e.g. if we have S =(2, 5) each player is only allowed to remove 2 or 5 beads. Now it is not always possible to make the xor-sum 0 and, thus, the strategy above is useless. Or is it?
your job is to write a program that determines if a position of S-Nim is a losing or a winning position. A position is a winning position if there is at least one move to a losing position. A position is a losing position if there are no moves to a losing position. This means, as expected, that a position with no legal moves is a losing position.
Input
Input consists of a number of test cases. For each test case: The first line contains a number k (0 < k ≤ 100 describing the size of S, followed by k numbers si (0 < si ≤ 10000) describing S. The second line contains a number m (0 < m ≤ 100) describing the number of positions to evaluate. The next m lines each contain a number l (0 < l ≤ 100) describing the number of heaps and l numbers hi (0 ≤ hi ≤ 10000) describing the number of beads in the heaps. The last test case is followed by a 0 on a line of its own.
Output
For each position: If the described position is a winning position print a 'W'.If the described position is a losing position print an 'L'. Print a newline after each test case.
Sample Input
2 2 5
3
2 5 12
3 2 4 7
4 2 3 7 12
5 1 2 3 4 5
3
2 5 12
3 2 4 7
4 2 3 7 12
0
Sample Output
LWW
WWL
。。。题目贼恶心,题意大概是这样的,首先输入K 表示一个集合的大小 之后输入这个集合 表示对于这些堆石子中只能拿去这个集合中的元素的个数
之后输入一个m 表示接下来对于这个集合要进行m次询问
之后m行 每行输入一个n 表示有n个堆 每堆有ni个石子 问这一行所表示的状态是赢还是输 如果赢输入W否则L
第一行就是对f数组的输入了,但有点坑的是这个输入不一定是从小到大的,所以还要排个序,不然会WA,接下来就是m个询问了,博主是个傻叉QAQ,我把SG函数放在m个询问里面了,对于每一个的n找到它最大的石子的数量然后SG跑一遍。。。果断T飞QAQ。
其实这么写没有必要,题目刚开始给你的f 数组就是让你预处理,但我们并不知道石子的数量啊?设个上限就好了,和之前HDU-1848一样,这样写就成功地降低了一大截的复杂度。然而这么写还是T了。。。。对,这一次我找了很久的BUG。。。。最后还是没找到,绝望之下将标记数组改成了bool。。。然后过了qwq也就是说清空数组的时候memset()清空bool类型的会比int之类的要快非常多。。。一个是T,一个只跑了405ms。。。。
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e6;
const int mac = 1e4 + 10;
const int inf = 1e8 + 10;
int f[105];
int sg[mac];
bool s[mac];
void SG(int n);
int main()
{
int n, m, p, ss, x;
while (scanf("%d", &ss)) {
if (ss == 0) break;
for (int i = 1; i <= ss; i++) {
scanf("%d", &f[i]);
}
sort(f+1,f+1+ss);
scanf("%d", &m);
SG(ss);
while (m--) {
scanf("%d", &n);
int v = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
v ^= sg[x];
}
if (v) printf("W");
else printf("L");
}
printf("\n");
}
return 0;
}
void SG(int n)
{
memset(sg, 0, sizeof(sg));
for (int i = 1; i <= mac-5; i++) {
memset(s, false, sizeof s);
for (int j = 1; f[j] <= i && j <= n; j++)
s[sg[i - f[j]]] = true;
for (int j = 0;; j++)
if (!s[j]) { sg[i] = j; break; }
}
}