Problem

Input

Output

Hint

Solution

  刚看到题就知道是正解想不出暴力打不出的博弈。。。
  比赛时我也想了一会,但是只想到了40points。。。

40points:状压DP or 记忆化搜索

  40points的m≤20,可以考虑二进制压缩状态。
  对于每一位,为0表示无棋子,为1表示有棋子。
  这样的话,状态数是O(2m)O(2m)O(2^m)级别的。对于每个状态的每一位,可以处理出它会往后跳到哪一格。
  设tot[i]表示状态i的必胜走法。显然,如果i的第m位为1,则肯定是必胜的。此时,i≥2m−1i≥2m−1i≥2^{m-1}。
  考虑逆着DP。也就是说,对于某个必败态,将其中的某个棋子往左移动,转化为某个必胜态,使其必胜走法++。可以发现,如果我们正着跳,肯定会使状态i增大;那么我们要逆着DP,则可以逆序枚举状态i来转移。
  时间复杂度:O(2mm)O(2mm)O(2^mm)。

Code
#include <cstdio>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;const int M=21,S=(1<<M)-1;
int i,j,k,m,n,s,fir,a,st;
ll tot[S];int calc(int s)//计算状态s中有多少个棋子
{return s?(s&1)+calc(s>>1):0;
}
inline int pos(int x){return 1<<x-1;}//返回x的状态
inline bool in(int x){return pos(x)&i;}//判断位于x的棋子是否在状态i中
int main()
{scanf("%d%d",&m,&n);s=(1<<m)-1;fo(i,1,n)scanf("%d",&a),st+=pos(a);//st记录起始状态fd(i,s-1,st+1)if(!tot[i]&&calc(i)==n){fir=0;fo(j,1,m){if(!in(j)){fir=j;continue;}if((!in(m)||j==m)&&fir){k=i-pos(j)+pos(fir);tot[k]++;}}}printf("%lld",tot[st]);
}

100points:阶梯nim

  其实这题可以转化成阶梯nim。
  首先,我们需要特判a[n]=m-1的情况。此时,答案为末尾连续的棋子个数。因为末尾的那堆棋子都可以一步移到m。
  那么,a[n] < m-1怎么办?
  譬如有如下的一块板子:

  如果此时所有的棋子都聚集在m-2(所有棋子连续,最后一个棋子在m-2),那么这是一个必败态。所以可以把第m-2个位置设为第0层。
  然后,我们将连续的棋子放在同一层;若碰到空格,则忽略其中一个,然后令其他的空格独踞一层。
  也就是说,我们每碰到一个棋子,就加进当前层;每碰到一个空格,就令层数++。于是,两个相邻(a[i]与a[i+1])棋子的层数差即为它们间的空格数。
  所以说,上图中的第0层有2个棋子(即a[5]、a[6]);第3层有3个棋子(即a[2]、a[3]、a[4]);第4层有1个棋子(即a[1])。如果我们将a[1]后移一格,它就会与a[2]、a[3]、a[4]连在一起;所以对应它往下跳一层,就可以与a[2]、a[3]、a[4]处在同一层。
  于是,这就转化成了一个阶梯nim游戏。SG=奇数层棋子数的异或和。
  当SG=0时必败,SG=1时必胜。但这题并不让我们判断是否必胜,而是要我们求必胜走法方案数。
  我们可以分类讨论:从奇数层移到偶数层,设那个奇数层有a个棋子,此时相当于取走若干个棋子,那么只要它满足a>SG^a,我们就可以取走若干个,使它剩下SG^a个,然后SG值就会变成0,所以此时ans++;从偶数层移到奇数层,设偶数层有c个棋子,奇数层有d个棋子,只要它满足c+d≥SG^d且d < SG^d,我们就可以从c移若干个给d,把d补至SG^d个,SG值就会变成0,所以此时也让ans++。
  当然,这可能有O(m)O(m)O(m)层,我们只需记录有棋子的层的信息即可。
  时间复杂度:O(n)O(n)O(n)。

Code

#include <cstdio>
#include <cctype>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;const int N=1e6+9;
int i,j,m,n,a[N],t,b[N],c[N],d[N],SG,tot;void read(int&x)
{char ch=getchar();x=0;for(;!isdigit(ch);ch=getchar());for(;isdigit(ch);x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
}
int main()
{read(m);read(n);fo(i,1,n)read(a[i]);if(a[n]==m-1){fd(i,n-1,1)if(a[i]+1<a[i+1])break;printf("%d",n-i);return 0;}a[0]=-1;a[n+1]=m-1;for(i=n;i;i=j-1){t+=a[i+1]-a[i]-1;fd(j,i,1)if(a[j-1]+1<a[j])break;if(t&1) b[++b[0]]=i-j+1;elseif(t){c[++c[0]]=i-j+1;if(a[i]+2==a[i+1])d[c[0]]=b[b[0]];}}fo(i,1,b[0])SG^=b[i];if(!SG){putchar('0');return 0;}fo(i,1,b[0])tot+=(b[i]>=(b[i]^SG));fo(i,1,c[0])tot+=(c[i]+d[i]>=(d[i]^SG)&&d[i]<(d[i]^SG));printf("%d",tot);
}

【JZOJ4178】【NOI2015模拟YDC】游戏(阶梯nim游戏)相关推荐

  1. 【NOI2015模拟YDC】游戏

    Description 有一个有n个格子的东西,其中有一些格子中有棋子.每一次先手可以选择一个棋子移到它右边第一个没有棋子的位置.先占领格子n的玩家获胜.求先手必胜的方案数. n<=10^9,棋 ...

  2. 翻棋子游戏与Nim游戏

    翻棋子游戏: 题意:一个棋盘上每个格子有一个棋子,每次操作可以随便选一个朝上的棋子(x,y),代表第i行第j列的棋子,选择一个形 如(x,b)或(a,y)(其中b < y,a < x)的棋 ...

  3. 博弈论 1.Introduction(组合游戏基本概念、对抗搜索、Bash游戏、Nim游戏)

    1.博弈 博弈论是研究具有斗争或竞争性质现象的数学理论和方法. 每个玩家都有一个偏好,A一般是希望A赢,如果不可以的话就倾向于 平局,B一般倾向B赢,达不到的话就倾向于平局.他们的每一步组成了一个&q ...

  4. 组合游戏(Nim游戏)——SG函数

    SG为0的点(必败点)能到达的肯定都是SG不为0的点(必胜点): SG不为0的点(必胜点)一定能通过某种方式到达SG为0的点(必败点). 组合游戏典型例题: 给定n堆石子以及一个由k个不同正整数构成的 ...

  5. 博弈论(Nim游戏、有向图游戏之SG函数)

    这里写目录标题 经典NIM游戏 Nim游戏属于公平组合游戏ICG 有向图游戏(SG函数) Mex运算 SG函数 单个有向图(一堆石子) 求SG值(记忆化递归) 有向图游戏的和 ,(多个有向图(多堆石子 ...

  6. 洛谷 P2197 nim游戏

    洛谷 P2197 nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取 ...

  7. Nim 游戏和 SG 函数

    Nim游戏 Nim游戏定义 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于"Impartial Combinatorial Games"(以下 ...

  8. 【acm 博弈论 】 之 Nim游戏与sg函数

    文章目录 前言 巴什博弈 威佐夫博弈 Nim游戏 Nim游戏与sg函数 题目 题意 样例 思路 代码 前言 从今天开始复习和整理下acm的部分模块,从博弈论开始. 著名的"取石子" ...

  9. 【学习笔记】NIM游戏与SG函数初探

    公平组合游戏ICG 游戏条件介绍: 由两名玩家交替行动 游戏进程的任意时刻,可以执行的合法行动与轮到的玩家无关 若当前玩家无法行动,则判负 则称该组合游戏为公平组合游戏.如NIM游戏等即是经典的公平组 ...

最新文章

  1. 适合ipad的python编程软件-如何用iPad运行Python代码?
  2. Html之head部分详解
  3. EMR、EHR和PHR的定义与对比
  4. 关于Android中Service的手动、自动以及其在特殊条件下的重启
  5. linux跟踪内存块,在Linux程序中跟踪活动使用的内存
  6. php实现中英文网站插件,php官网英文自动跳中文
  7. mysql 如何磁阵_Raid教程 全程图解手把手教你做RAID
  8. mysql实际应用在哪里_MySQL数据库的实际应用步骤
  9. python中json如何存放字节数组中_测试面试题集锦(四)| Linux 与 Python 编程篇(附答案)...
  10. 获取json配置_ASP.NET Core集成Nacos配置中心之适配多格式配置
  11. Mac硬件温度管理软件TG Pro
  12. Shutdown In Period 1.0
  13. 教程篇(6.4) 02. 路由、会话和性能SLA ❀ SD-WAN ❀ Fortinet 网络安全架构师 NSE7
  14. 唐门暗器之私有云排名
  15. 【网络】Wireshark分析RST消息
  16. 基于python的 ping 网络状态监测方法 亲测有效
  17. 十分钟入门Visio,不行来砍我!
  18. 基于Altium Designer10的PCB设计入门过程
  19. java 内存模型面试_Java面试- JVM 内存模型讲解
  20. 分布式微服务项目实现高并发高可用高性能可以使用到的方案

热门文章

  1. Android开发之路之 webview
  2. yum 源没有php7.0,yum安装最新版php7的操作方法
  3. Object.entries()
  4. 微信小程序申请医疗-就医服务类目解决办法
  5. 关于ES2020语法2345加速浏览器不兼容问题
  6. 【miscellaneous】视频浓缩摘要简介
  7. 非常好理解的python re正则表达式入手
  8. OpenCV里的常用Rect用法
  9. 一周XX思考(第12期)
  10. ERP系统-库存子系统-申购单