Nim游戏的一个扩展——51nod 1661 黑板上的游戏+LA 5059 Playing With Stones

原创 2016年08月30日 21:11:44

前几天做过一道题目,是Nim游戏的一个扩展,也不能说扩展吧,只是说另一种常见的状态。

问题引入:

给定n堆石子,每堆石子有vi(1<=vi<=1e5) 个,每次可以取一堆中的一些石子,使得剩下的石子为1到vi/k个,为最后的是先手胜,还是后手胜,如果先手胜则输出相应的操作策略。

思考:

当k==2的时候,显然就退化成了la 5059 的题目,我们以此为基础来考虑,肯定要先计算出sg的函数表,然后观察规律,lrj在训练指南中说的很清楚,打表的规则也很简单,下面给出lrj所打出的表:
0 1 0 2 1 3 0 4 2 5
当然,lrj是从奇偶性来分析的,那么很容易得出
sg(x)=n%2==0?sg(n/2)这样的结论,因为k==2,刚好有一些特性被提现出来了。所以:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll sg(ll n)
{
    return n%2==0 ? n/2 : sg(n/2);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        ll x;
        scanf("%d",&n);
        ll ans=0;
        while(n--)
        {
            scanf("%lld",&x);
            ans^=sg(x);
        }
        if(ans)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

那么当k>2的时候,又该怎么去解决?难道比葫芦画瓢?要推出
sg=(n%k==0)?n/k:sg(n/k) 这样的结论,如果真的这样,我只能说比葫芦画瓢的能力只用在了记答案上,这种能力应该是一种分析该问题的方法,正确的解法无非是打sg表,寻找规律。

笔者随手推了一下,那么打出的表如下:

k==3: 0 1 2 0 3 4 1 5 6
k==4:0 1 2 3 0 4 5 6 1 7 8 9

可以发现,都有123456……这个序列,而再去翻看上面的n==2的情况,发现都存在这样的规律,但是,好像没什么用,具体编程还是没办法操作,再去细看,发现打断123456这个序列的的下标x都是x%k==1,而且去掉123456这样的数后得到的都是原序列,那么,也就是说,当x%k==1时,sg(x)=sg(x/k) 否则,这样的123456序列实际上是由x-阶梯层数得到的,什么是阶梯层数,当k==3的时候x=1,2,3就属于第一层,x=4,5,6 就属于第二层,那么容易得出:

x%k==1 ? sg(x/k) : x-x/k-(x%k!=0);

于是,上题的第二种解法为:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll k=2;
ll sg(ll x){
   if (x==1) return 0;
   return x%k==1 ? sg(x/k) : x-x/k-(x%k!=0);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        ll x;
        scanf("%d",&n);
        ll ans=0;
        while(n--)
        {
            scanf("%lld",&x);
            ans^=sg(x);
        }
        if(ans)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

而对于51nod中要求求必胜操作时,只需预处理一下sg值,然后枚举每一位根据sg值来逆推符合条件的x即可。

提交地址:
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1661

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N=1e5+5;

ll n,k,sl[N],sr[N],v[N],vt[N];
ll sg(ll x){
   if (x==1) return 0;
   return x%k==1 ? sg(x/k) : x-x/k-(x%k!=0);
}

int main()
{
    sl[0]=sr[n+1]=0;
    cin>>n>>k;ll p=0,ans=0;
    for (int i=1;i<=n;i++){
        scanf("%lld",v+i);
        vt[i]=sg(v[i]);
        sl[i]=sl[i-1]^vt[i];
    }
    for (int i=n;i>=1;i--) sr[i]=sr[i+1]^vt[i];
    for (int i=1;i<=n;i++){
      ll tt=sl[i-1]^sr[i+1],tx=ceil(1.0*v[i]/k);
      if (v[i]==1||vt[i]<=tt) continue;
      ll ttl=(ll)(1.0*tt*k/(k-1)+1);
      if (ttl%k==1) ttl--;
      for (int j=0;j<64;j++){
          if (ttl>=tx) break;
          ttl=ttl*k+1;
      }
      if (ttl<v[i]&&sg(ttl)==tt){
            p=i;ans=ttl;break;
        }
    }
    if (sl[n]) cout<<"Alice "<<p<<" "<<ans<<endl;
    else puts("Bob");
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

Nim游戏,Grundy函数介绍

Nim游戏,Grundy函数介绍部分翻译自:http://www.cut-the-knot.org/ctk/May2001.shtmlNim是一种很古老又很迷人的双人参与的数学游戏。这个游戏的名字和相...
  • mystoryfantacy
  • mystoryfantacy
  • 2016年06月10日 21:01
  • 390

nim游戏详解(易懂)

Nim游戏的概述: 还记得这个游戏吗? 给出n列珍珠,两人轮流取珍珠,每次在某一列中取至少1颗珍珠,但不能在两列中取。最后拿光珍珠的人输。 后来,在一份资料上看到,这种游戏称为“拈(Nim)”。据说,...
  • Summer__show_
  • Summer__show_
  • 2017年04月15日 16:57
  • 1282

Nim 游戏及其变形

Nim 在博弈中经常出现,很多看似复杂的题目,在分析和变形之后就回归了最初的nim游戏。 经典的nim游戏 一共有N堆石子,编号1..n,第i堆中有个a[i]个石子。 每一次操作Alice和Bob...
  • clover_hxy
  • clover_hxy
  • 2016年12月22日 20:25
  • 1460

博弈论 Nim游戏与SG函数

SG函数&Nim游戏
  • neighthorn
  • neighthorn
  • 2016年07月09日 21:41
  • 615

取石子游戏详解NIM

取石子游戏详解NIM 分类: 编程之美2014-09-13 09:38 478人阅读 评论(3) 收藏 举报 编程之美 目录(?)[+] http:...
  • acm_BaiHuzi
  • acm_BaiHuzi
  • 2014年11月30日 14:52
  • 1227

51nod - 1661 黑板上的游戏 - 博弈论

题目:51nod 算法马拉松 17(告别奥运)A 黑板的游戏 题意:两个人轮流玩擦数字游戏,给定n个数ai(i=1,2,3,...,n)和一个k,(1≤n≤105,2≤k≤1018,1≤ai≤101...
  • qq_23323877
  • qq_23323877
  • 2016年08月31日 15:05
  • 283

[51nod1824]染色游戏

Description有 n 个红球, m 个蓝球,从中取出 x 个红球和 y 个蓝球排成一排的得分是 rx⋅by ,其中 r0=b0=1 。 定义 f(t) 表示恰好取出 t 个球排成一排的所有可...
  • alan_cty
  • alan_cty
  • 2017年11月08日 16:34
  • 140

51Nod-1534-棋子游戏

ACM模版描述题解不知道为嘛在话题区添加了一个博弈论,这道题猛一看,感觉就是博弈论,但是感觉好刁钻,竟然还真的有人用博弈论博了出来,看来是我的功底不够深,用博弈论搞的人是把这道题转化为了一个拦截问题,...
  • f_zyj
  • f_zyj
  • 2016年12月16日 10:08
  • 388

C++抽象编程——回溯算法(5)——Nim游戏代码及其反思

实话,距离上一篇博客发表完到现在,我为了这个代码写了一个多小时。里面的思维方式让我受益匪浅。很累,但是很开心。下面我就分享出来大家一起看看。我写的时候调试了几次,最后我把我几次调试的过程都写在了注释里...
  • redRnt
  • redRnt
  • 2017年05月09日 23:16
  • 454

51nod 1459 迷宫游戏

1459 迷宫游戏 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 你来到一个迷宫前。该迷宫由若干个房间组成,每个房间都有一个得分,...
  • qq_32734731
  • qq_32734731
  • 2016年12月08日 19:24
  • 321
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Nim游戏的一个扩展——51nod 1661 黑板上的游戏+LA 5059 Playing With Stones
举报原因:
原因补充:

(最多只允许输入30个字)