取石子的几个找sg函数的问题

1.light oj 1296 :传送门

规则,n堆,每次可以从一堆取1到n/2个。

分析:

打表找sg规律,发现

if n&1 sg(x)=sg(x/2);

else sg(x)=x/2;

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1000;
/*打表。。。
int sg[maxn];

int get_sg(int x){
    if(sg[x]!=-1) return sg[x];
    int vis[maxn];
    memset( vis,0,sizeof(vis));
    for(int i=1;i<=x/2;i++)
        vis[get_sg(x-i)]=1;
    for(int i=0;;i++){
        if(!vis[i])
            return sg[x]=i;
    }
}

void init(){
    memset(sg,-1,sizeof(sg));
    sg[0]=1;
    for(int i=1;i<maxn;i++) sg[i]=get_sg(i);
}
*/

int get_sg(int x){
    if(x&1) return get_sg(x>>1);
    else return x>>1;
}
int main()
{
    int t,n,x,cas=1;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        int ans = 0;
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            ans^=get_sg(x);
        }
        printf("Case %d: ",cas++);
        if(!ans) puts("Bob");
        else puts("Alice");
    }
    return 0;
}

2.light oj 1199 传送门

规则:

n堆石头,每次可以把其中的一堆分为数目不相等的两堆,谁不能移则输。

分析:

每次的操作是相互独立的,

则sg[x] = mex(sg[1]^sg[x-1],sg[2]^sg[x-2],...,sg[(x-1)/2]^sg[x-(x-1)/2]);

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 1e4+10;

int sg[maxn];

int get_sg(int x){
    if(sg[x]!=-1) return sg[x];
    int vis[maxn];
    memset(vis,0,sizeof(vis));
    int half = x/2 - (x%2==0);
    for(int i=1;i<=half;i++)
        vis[get_sg(x-i)^get_sg(i)]=1;
    for(int i=0;;i++){
        if(!vis[i]) return sg[x]=i;
    }
}

void init(){
    memset(sg,-1,sizeof(sg));
    sg[0]=0;
    sg[1]=0;
    sg[2]=0;
    for(int i=1;i<maxn;i++)
        sg[i]=get_sg(i);
}

int main()
{
    init();
    int n,x,t,cas=1;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        int ans = 0;
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            ans^=sg[x];
        }
        printf("Case %d: ",cas++);
        if(!ans) puts("Bob");
        else puts("Alice");
    }
    return 0;
}

3.lightoj 1253 传送门

分析

当n个数不全都是1时就是nim;

否者判断n的奇偶性

代码如下:

#include <cstdio>
int main()
{
    int j,i,t,n,x,res;
    bool flag;
    scanf("%d",&t);
    for(j=1;j<=t;++j)
    {
        res=0;
        flag=true;
        scanf("%d",&n);
        for(i=0;i<n;++i)
        {
            scanf("%d",&x);
            if(x!=1) flag=false;
            res=res^x;
        }
        if(flag&&n%2||!flag&&res==0) printf("Case %d: Bob\n",j);
        else printf("Case %d: Alice\n",j);
    }
    return 0;
}
时间: 2024-12-28 01:22:11

取石子的几个找sg函数的问题的相关文章

【LA5059】Playing With Stones (SG函数)

题意:有n堆石子,分别有a[i]个.两个游戏者轮流操作,每次可以选一堆,拿走至少一个石子,但不能拿走超过一半的石子. 谁不能拿石子就算输,问先手胜负情况 n<=100,1<=a[i]<=2e18 思路:打表找SG函数的规律 当n为偶数时,SG(n)=n/2 当n为奇数时,SG(n)=SG(n/2) 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algo

BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏 [Nim游戏 SG函数]

小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问你他是否有必胜策略,如果有,第一步如何取石子. N≤10 Ai≤1000 裸SG函数啊 然而我连SG函数都不会求了,WA了一会儿之后照别人代码改发现vis公用了... #include <iostream> #include <cstdio> #include <cstring> #includ

bzoj 1874 取石子游戏 题解 &amp;amp; SG函数初探

[原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 334  Solved: 122 [Submit][Status] Description 小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这种,每一个人每次能够从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问你他是否有必胜策略,假设有,第一步怎样取石子. In

bzoj 1874 取石子游戏 题解 &amp; SG函数初探

[原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 334  Solved: 122 [Submit][Status] Description 小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问你他是否有必胜策略,如果有,第一步如何取石子. In

BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏(SG函数)

Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 871  Solved: 365[Submit][Status][Discuss] Description 小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子, 每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问你他是否有必胜策略,如果有 ,第一步如何取石子. Input 输入文件的第一行为石子的堆数N 接下来N行,每行一个数A

[BZOJ 1874] [BeiJing2009 WinterCamp] 取石子游戏 【博弈论 | SG函数】

题目链接:BZOJ - 1874 题目分析 这个是一种组合游戏,是许多单个SG游戏的和. 就是指,总的游戏由许多单个SG游戏组合而成,每个SG游戏(也就是每一堆石子)之间互不干扰,每次从所有的单个游戏中选一个进行决策,如果所有单个游戏都无法决策,游戏失败. 有一个结论,SG(A + B + C ... ) = SG(A)^SG(B)^SG(C) ... 这道题每堆石子不超过 1000 , 所以可以把 [0, 1000] 的 SG 值暴力求出来,使用最原始的 SG 函数的定义, SG(u) = m

LA 5059 (找规律 SG函数) Playing With Stones

题意: 有n堆石子,两个人轮流取,每次只能取一堆的至少一个至多一半石子,直到不能取为止. 判断先手是否必胜. 分析: 本题的关键就是求SG函数,可是直接分析又不太好分析,于是乎找规律. 经过一番“巧妙”的分析,有这样一个规律: 如果n是偶数,SG(n) = n / 2; 如果n是奇数,SG(n) = SG(n / 2); 这道题的意义不在于规律是什么,而是要自己能够写出求SG函数值的代码.顺便再体会一下mex(S)的含义. 1 #include <cstring> 2 3 const int

Nim or not Nim?(hdu3032+SG函数)取走-分割游戏,经典

小k,终于忍不住了...正在笔记本上装win10,有点小激动. Nim or not Nim? Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3032 Description Nim is a two-player mathematic game of strategy in which players take turns remov

[hdu-5795]A Simple Nim 博弈 尼姆博弈 SG函数打表找规律

[题目]题目链接 Two players take turns picking candies from n heaps,the player who picks the last one will win the game.On each turn they can pick any number of candies which come from the same heap(picking no candy is not allowed).To make the game more int