ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

硬币博弈的SG值规律

2019-10-10 21:04:32  阅读:276  来源: 互联网

标签:博弈 .. 硬币 值为 ii SG define


翻硬币游戏

 $N$枚硬币排成一排,有的正面朝上,有的反面朝上。我们从左开始对硬币按1 到N编号。

最右边那个硬币的必须是从正面翻到反面,.谁不能翻谁输。

局面的SG值为局面中每个正面朝上的棋子单一存在时的SG值的异或和

1.每次只能翻一个硬币,

显然,每个硬币的SG值为1

2.每次能翻转一个或两个(不用连续)

每个硬币的SG值为其从左到右的编号位置,从0开始

#include <bits/stdc++.h>
#define ll long long
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl
using namespace std;//head
const int maxn=1e5+10,maxm=2e6+10;
int casn,n,m,k,kase;
int sg[maxn];
int getmex(bool vis[]){
  int mex=0;
  while(vis[mex]) ++mex;
  return mex;
}
int getsg(int now){
  if(~sg[now]) return sg[now];
  bool vis[now+1]={0};
  rep(i,1,now-1) vis[getsg(i)]=1;
  vis[now]=1;
  return sg[now]=getmex(vis);
}
int main(){IO;
  memset(sg,-1,sizeof sg);
  cin>>n;
  getsg(n);
  showa(sg,1,n);
}

 3.每次只能翻转连续k枚硬币

每个硬币的SG值为0000...100000..1,其中每k个为一个周期,每个周期前k-1个为0

#include <bits/stdc++.h>
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl
using namespace std;//head
const int maxn=1e5+10,maxm=2e6+10;
int casn,n,m,k,kase;
int sg[maxn];
int getmex(bool vis[]){
  int mex=0;
  while(vis[mex]) ++mex;
  return mex;
}
int getsg(int now,int k){
  if(~sg[now]) return sg[now];
  bool vis[now+1]={0};
  int flag=0;
  rep(i,now-k+1,now-1){
    flag^=getsg(i,k);
  }
  vis[flag]=1;
  return sg[now]=getmex(vis);
}
int main(){IO;
  memset(sg,-1,sizeof sg);
  cin>>n>>k;
  rep(i,0,k-1) sg[i]=0;
  getsg(n,k);
  showa(sg,1,n);
}

4:每次翻动第X个硬币后,必须翻动其左侧最近K个硬币中的一个,除非X是小于等于3的

SG值为1,2,3,4..K,0,1,2,3,4..K,0每K+1个数字为一个周期

 

#include <bits/stdc++.h>
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl
using namespace std;//head
const int maxn=1e5+10,maxm=2e6+10;
int casn,n,m,k,kase;
int sg[maxn];
int getmex(bool vis[]){
  int mex=0;
  while(vis[mex]) ++mex;
  return mex;
}
int getsg(int now,int k){
  if(~sg[now]) return sg[now];
  bool vis[now+1]={0};
  rep(i,max(0,now-k),now-1){
    vis[getsg(i,k)]=1;
  }
  return sg[now]=getmex(vis);
}
int main(){
  memset(sg,-1,sizeof sg);
  cin>>n>>k;
  getsg(n,k);
  showa(sg,1,n);
}

 

 5.每次可以翻额外的0,1,2,3..k个硬币

 

标签:博弈,..,硬币,值为,ii,SG,define
来源: https://www.cnblogs.com/nervendnig/p/11650523.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有