sg函数模板

hdu1536:

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
 
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=10010;
int sg[maxn],s[maxn],k;
bool vis[maxn];



void SG(int n){
    memset(sg,0,sizeof(sg));
    for(int i=1;i<maxn;i++){
        memset(vis,false,sizeof(vis));
        for(int j=0;j<n&&s[j]<=i;j++) 
            vis[sg[i-s[j]]]=1;
        for(int j=0;j<maxn;j++){
            if(!vis[j]){
                sg[i]=j;
                break;
            }
        }
    }
}







int main(){
    int m,l,x;
    while(~scanf("%d",&k)){
        if(k==0) break;
        for(int i=0;i<k;i++)
        scanf("%d",&s[i]);
        sort(s,s+k);
        SG(k);
        scanf("%d",&m);
        while(m--){
            scanf("%d",&l);
            int sum=0;
            while(l--){
                scanf("%d",&x);
                sum^=sg[x];
            }
            if(sum==0)
                printf("L");
            else 
                printf("W");
        }
            printf("
");
    }    
} 

1847

大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此。当然,作为在考场浸润了十几载的当代大学生,Kiki和Cici更懂得考前的放松,所谓“张弛有道”就是这个意思。这不,Kiki和Cici在每天晚上休息之前都要玩一会儿扑克牌以放松神经。
“升级”?“双扣”?“红五”?还是“斗地主”?
当然都不是!那多俗啊~
作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的:
1、  总共n张牌;
2、  双方轮流抓牌;
3、  每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4、  抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢?
当然,打牌无论谁赢都问题不大,重要的是马上到来的CET-4能有好的状态。

Good luck in CET-4 everybody!
 
Input
输入数据包含多个测试用例,每个测试用例占一行,包含一个整数n(1<=n<=1000)。
 
Output
如果Kiki能赢的话,请输出“Kiki”,否则请输出“Cici”,每个实例的输出占一行。
 
Sample Input
1 3
 
Sample Output
Kiki Cici
 
Author
lcy
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  1849 1846 1850 2147 2149
 
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=10010;
int sg[maxn],s[maxn],k;
bool vis[maxn];



void SG(int n){
    memset(sg,0,sizeof(sg));
    for(int i=1;i<maxn;i++){
        memset(vis,false,sizeof(vis));
        for(int j=0;j<n&&s[j]<=i;j++) 
            vis[sg[i-s[j]]]=1;
        for(int j=0;j<maxn;j++){
            if(!vis[j]){
                sg[i]=j;
                break;
            }
        }
    }
}







int main(){
    int m,l,x;
        int i;
        for(i=0;(1<<i)<=1000;i++){
            s[i]=1<<i;
        }
        SG(i);    
    while(~scanf("%d",&k)){
        int sum=0^sg[k];
        if(sg[k]==0) printf("Cici
");
        else printf("Kiki
");
    }    
} 

1848

任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:
F(1)=1;
F(2)=2;
F(n)=F(n-1)+F(n-2)(n>=3);
所以,1,2,3,5,8,13……就是菲波那契数列。
在HDOJ上有不少相关的题目,比如1005 Fibonacci again就是曾经的浙江省赛题。
今天,又一个关于Fibonacci的题目出现了,它是一个小游戏,定义如下:
1、  这是一个二人游戏;
2、  一共有3堆石子,数量分别是m, n, p个;
3、  两人轮流走;
4、  每走一步可以选择任意一堆石子,然后取走f个;
5、  f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
6、  最先取光所有石子的人为胜者;

假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。
 
Input
输入数据包含多个测试用例,每个测试用例占一行,包含3个整数m,n,p(1<=m,n,p<=1000)。
m=n=p=0则表示输入结束。
 
Output
如果先手的人能赢,请输出“Fibo”,否则请输出“Nacci”,每个实例的输出占一行。
 
Sample Input
1 1 1 1 4 1 0 0 0
 
Sample Output
Fibo Nacci
 
Author
lcy
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  1850 1849 1846 2147 2149
 
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1010;
int sg[maxn],s[maxn],k;
bool vis[maxn];



void SG(int n){
    memset(sg,0,sizeof(sg));
    for(int i=1;i<maxn;i++){
        memset(vis,false,sizeof(vis));
        for(int j=0;j<n&&s[j]<=i;j++) 
            vis[sg[i-s[j]]]=1;
        for(int j=0;j<maxn;j++){
            if(!vis[j]){
                sg[i]=j;
                break;
            }
        }
    }
}







int main(){
    int m,n,p;
    s[0]=1;
    s[1]=2;
    int i;
    for(i=2;s[i-1]+s[i-2]<=1000;i++) s[i]=s[i-1]+s[i-2];
    SG(i);
    while(~scanf("%d%d%d",&m,&n,&p)){
        if(m==0&&n==0&&p==0) break;
        int sum=0^sg[m]^sg[n]^sg[p];
        if(sum==0) printf("Nacci
");
        else printf("Fibo
");
    }    
} 
原文地址:https://www.cnblogs.com/ellery/p/11672284.html