poj 2960 S-Nim(SG函数)

S-Nim

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 3694   Accepted: 1936

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

Source

Svenskt Mästerskap i Programmering/Norgesmesterskapet 2004

【思路】

SG函数。

裸ti ,注意下sg和vis的大小就好了 :)

【代码】

 1 #include<cstdio>
 2 #include<cstring>
 3 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
 4 using namespace std;
 5
 6 int n,m,a[101],sg[10001];
 7
 8 int dfs(int x) {
 9     if(sg[x]!=-1) return sg[x];
10     if(!x) return sg[x]=0;
11     int vis[10001];                    //size of [si]
12     memset(vis,0,sizeof(vis));
13     FOR(i,0,n)
14         if(x>=a[i]) vis[dfs(x-a[i])]=1;
15     for(int i=0;;i++)
16         if(!vis[i]) return sg[x]=i;
17 }
18
19 int main() {
20     while(scanf("%d",&n)==1 && n) {
21         FOR(i,0,n) scanf("%d",&a[i]);
22         scanf("%d",&m);
23         memset(sg,-1,sizeof(sg));
24         FOR(i,0,m) {
25             int x,v,ans=0;
26             scanf("%d",&x);
27             FOR(j,0,x)
28                 scanf("%d",&v) , ans^=dfs(v);
29             if(ans) printf("W");
30             else printf("L");
31         }
32         putchar(‘\n‘);
33     }
34     return 0;
35 }
时间: 2024-08-02 13:48:04

poj 2960 S-Nim(SG函数)的相关文章

hdu 1536 S-Nim|| poj 2960 S-Nim (sg函数)

#include <stdio.h> #include <string.h> int s[110]; int sg[10010],hash[110]; int n, m; int getsg(int x) //sg模板 { int i; if(sg[x] != -1) return sg[x]; memset(hash,0,sizeof(hash)); for(i = 0; i < n; i++) { if(x >= s[i]) { sg[x - s[i]] = get

POJ 2960 S-Nim 博弈论 sg函数

http://poj.org/problem?id=2960 sg函数几乎是模板题. 调试代码的最大障碍仍然是手残在循环里打错变量名,是时候换个hydra产的机械臂了[超想要.jpg] 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 #include<map> 7 using na

POJ 2960 S-Nim(SG函数模板题)

链接:https://vjudge.net/problem/POJ-2960 题意:每行输入首先给出一个数k,代表集合S的大小,接下来紧跟着k个数,表示集合S里的数.接下来一行数为m代表有m个游戏,后面m行每行第一个数字为n代表有n堆石子,后面紧跟着n个数代表每堆石子的个数.多组数据,做到0结束 对于每组数据,我们要输出n个字母,第i个字母为“W”代表第i个游戏先手必胜,“L”代表第i个游戏先手必败,做完一组数据后换行. 题解:模板题 #include <cstdio> #include &l

HDU 3032 Nim or not Nim?(sg函数)

题目链接 暴力出来,竟然眼花了以为sg(i) = i啊....看表要认真啊!!! #include <cstdio> #include <cstring> #include <iostream> using namespace std; #define LL __int64 int dp[10001]; int sg(int x) { int flag[10001],temp,i; if(dp[x] >= 0) return dp[x]; memset(flag,

hdu 3032 Nim or not Nim? sg函数

Nim or not Nim? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1056    Accepted Submission(s): 523 Problem Description Nim is a two-player mathematic game of strategy in which players take turn

POJ 2311 Cutting Game (sg函数)

给出一个N*M的纸片,每一次可以把一部分剪成两部分,谁剪出1*1的就赢了. http://poj.org/problem?id=2311 对于任何一个人,都不会先剪出1*n或者n*1,应该这样就必败了. 那我们考虑一个状态的后继中,最小的边也是2,这样就可以避免之前的问题,也不需要考虑类似ANTI-SG. 一旦出现2*2,2*3,3*2,这些都成了终止状态,不论怎么剪都会出现1*n,或者n*1 还是考察SG函数 # include<stdio.h> # include<algorithm

HDU 3032 Nim or not Nim?(sg函数博弈)

题目地址:HDU 3032 这题是很好用来练习sg函数打表的一题. 下面是sg函数值打表代码: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include &

poj 2960 S-Nim nim博弈grundy值计算法入门

题意: 给k堆石子,两人轮流向某一堆中拿,拿的个数要从给定的一个集合中取,没石子拿的输,问先手必胜还是必败. 分析: grundy值计算法的入门题. 代码: //poj 2960 //sep9 #include <iostream> #include <set> using namespace std; int s[128]; int grundy[10024]; int maxx; int num; int get_grundy(int x) { if(grundy[x]!=-1

HDU 1729 Stone Game 石头游戏 (Nim, sg函数)

题意:有n个盒子,每个盒子可以放一定量的石头,盒子中可能已经有了部分石头.假设石头无限,每次可以往任意一个盒子中放石头,可以加的数量不得超过该盒中已有石头数量的平方k^2,即至少放1个,至多放k^2个. 思路:跟常规nim的区别就是加了个限制“每次加的量不超平方”.盒子容量上限是100万,那么就不能直接计算SG了,会超时.sg打表后找规律.根据剩下多少个空位来决定sg值.都是0123456这样子递增的,碰到不能一次加满就变为0,然后继续递增,一直这样. 我的方案是,对于每个盒子大小,找到除了自己