点此看题面

大致题意: 有\(n\)个格子,让你摆放\(m\)个金币。二人博弈,每次选择一个金币向左移任意格,无法移动者输。问有多少种方案使先手必胜。

阶梯\(Nim\)

阶梯\(Nim\)的基本模型,就是有\(n\)层楼梯(从\(0\sim n-1\)编号),每层楼梯上有若干石子,每次可以取任一层楼梯上任意多个石子到下一层,无法移动者输。

它的解决方法就是,去掉所有编号为偶数的楼梯,然后对剩下的这些编号为奇数的楼梯当成普通\(Nim\)来做。

原理是,如果一人移动编号为偶数的楼梯上的石子到下一层,如移动第\(2n\)层的\(a\)个石子到第\(2n-1\)层,那么无论何时对方都可以把这\(a\)个石子接着从第\(2n-1\)层移动到第\(2n-2\)层,因为\(2n-2\)层是必然存在的。

所以,移动偶数层的石子相当于是无效的,就可以直接忽略。

此题转化

对于这道题,我们可以发现,如果把每两个金币之间的空格当作一堆石子,这就是一个典型的阶梯\(Nim\)。

也就是说,若要先手必胜,就要满足奇数堆石子个数异或值不为\(0\)。

这显然不好求,所以我们可以转而求异或值为\(0\)的方案数,再用总方案数\(C_n^m\)减去它即为答案。

动态规划

考虑如何求异或值为\(0\)的方案数。

可以在二进制下逐位\(DP\)。

我们设\(f_{i,j}\)表示满足二进制下从最高位至右数第\(i\)位异或值为\(0\),剩余石子总数为\(j\)的方案数

那么对于\(f_{i,j}\)的转移,我们可以枚举有\(k\)个奇数堆石子个数二进制下第\(i\)位为\(1\),其中因为要使异或值为\(0\),因此\(k\)为偶数。

转移方程为:

\[f_{i,j}=\sum C_{t1}^k\times f_{i+1,j+k\times2^i}
\]

其中\(t1\)表示奇数堆的个数。

计算答案

我们可以枚举满足所有奇数堆每一位异或值为\(0\)时所剩的石子个数\(i\),这就是偶数堆的石子个数。

则用插板法就可以求出异或值为\(0\)的方案数为:

\[\sum_{i=1}^{n-m}C_{i+t0-1}^{t0-1}\times f_{0,i}
\]

其中\(t0\)表示偶数堆的个数。

最后用\(C_n^m\)减去这一方案数就是答案。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 150000
#define M 50
#define LN 20
#define X 1000000009
#define Qinv(x) Qpow(x,X-2)
#define C(x,y) (1LL*Fac[x]*IFac[y]%X*IFac[(x)-(y)]%X)//组合数
using namespace std;
int n,m,Fac[N+5],IFac[N+5],f[LN+5][N+5];
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
RI i,j,k,t0,t1,res=0;scanf("%d%d",&n,&m),t0=(m>>1)+1,t1=m+1>>1;//计算偶数堆和奇数堆个数
for(k=max(n,2*m),Fac[0]=i=1;i<=k;++i) Fac[i]=1LL*Fac[i-1]*i%X;//初始化阶乘
for(IFac[k]=Qinv(Fac[k]),i=k-1;~i;--i) IFac[i]=1LL*IFac[i+1]*(i+1)%X;//初始化阶乘逆元
for(f[LN][n-m]=1,i=LN-1;~i;--i) for(j=0;j<=n-m;++j)//动态规划
for(k=0;k<=t1&&j+(k<<i)<=n-m;k+=2) f[i][j]=(C(t1,k)*f[i+1][j+(k<<i)]+f[i][j])%X;
for(i=0;i<=n-m;++i) res=(C(i+t0-1,t0-1)*f[0][i]+res)%X;//计算异或值为0的方案数
return printf("%d",(C(n,m)-res+X)%X),0;//输出答案
}

【洛谷5363】[SDOI2019] 移动金币(动态规划)的更多相关文章

  1. BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 分治

    原文链接http://www.cnblogs.com/zhouzhendong/p/8672434.html 题目传送门 - BZOJ4553 题目传送门 - 洛谷P4093 题解 设$Li$表示第$ ...

  2. 随手练——洛谷-P1002 过河卒(动态规划入门)

    题目链接:https://www.luogu.org/problemnew/show/P1002 题目还算良心,提醒了结果可能很大,确实爆了int范围, 这是一开始写的版本,用递归做的,先给地图做标记 ...

  3. 【洛谷】P2694 接金币(排序)

    题目描述 在二维坐标系里,有N个金币,编号0至N-1.初始时,第i个金币的坐标是(Xi,Yi).所有的金币每秒向下垂直下降一个单位高度,例如有个金币当前坐标是(xf, yf),那么t秒后金币所在的位置 ...

  4. 洛谷P1002 过河卒 题解 动态规划

    题目链接:https://www.luogu.com.cn/problem/P1002 题目大意 棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点.卒行走的规则:可以向下.或者向右.同时在棋盘 ...

  5. 洛谷P5774,可爱的动态规划。

    如此可爱的动态规划见过么? 相信各位都非常喜欢动态规划,那我就写一道可爱的动态规划的题解吧. 题目:https://www.luogu.com.cn/problem/P5774 题意: 题意“挺明白” ...

  6. 洛谷P1028.数的计算(动态规划)

    题目描述 我们要求找出具有下列性质数的个数(包含输入的自然数n): 先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理: 1.不作任何处理; 2.在它的左边加上一个自然数,但该自然 ...

  7. [洛谷P3878][TJOI2010]分金币

    题目大意:把$n(n\leqslant30)$个数分成两组,两组个数最多相差$1$,求出两组元素差的绝对值最小使多少 题解:模拟退火 卡点:$\exp$中的两个数相减写反,导致$\exp(x)$中的$ ...

  8. [洛谷P5361][SDOI2019]热闹又尴尬的聚会:构造题

    分析 构造方法 (截图自UOJ群) 可以使用std::set维护这个过程,不过据说可以做到\(O(n+m)\).. 正确性证明 题目中的要求等价于\((p+1)(q+1) > n\) 设每次找出 ...

  9. 洛谷P1002 过河卒(动态规划)

    题目描述 棋盘上 AA 点有一个过河卒,需要走到目标 BB 点.卒行走的规则:可以向下.或者向右.同时在棋盘上 CC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为 ...

随机推荐

  1. asp.net允许跨域配置web.config

    <configuration> <system.webServer> <modules> <add name="CultureAwareHttpMo ...

  2. 如何抓取 framework input 事件相关 log

    出现事件输入相关的问题时, 建议先 followhttp://429564140.iteye.com/blog/2355405来检测对应的设备是否有响应输入 如果没有响应输入,则可能是 driver ...

  3. 个人app如何收集用户日志

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/147 个人app如何收集用户日志,相信不少人对这个话题感兴 ...

  4. 如何在linux上有2个python的情况下安装gensim

    安装python的问题 https://blog.51cto.com/liqingbiao/2083869 安装gensim https://blog.csdn.net/zhujiyao/articl ...

  5. 获取Tekla属性方式

    XmlTextWriter xmlTextWriter = new XmlTextWriter((TextWriter) stringWriter); xmlTextWriter.Formatting ...

  6. python 基础学习笔记(6)--函数(1)

    ## **函数(1)** **函数的定义:** 1. [ ] 小时候大家应该都玩过乐高积木,只要通过想象和创意,可以用它怕拼凑出很多神奇的东西.随着学习的深入,编写的代码日益增加并且越来越复杂,所以需 ...

  7. Liu Junqiao:工作中用到的命令以及问题汇总

    工作中用到的命令以及问题汇总 2019-11-29 查看系统运行时间,这个问题是因为我们在阿里云上有个机器,在某一天发现这台机器上有的服务莫名奇妙的停了,然后排查时怀疑机器被重启过用如下如下命令查看了 ...

  8. 【测试基础】App测试要点总结

    测试工作过程中思维过程:测试人员常被看作Bug寻找者,程序的破坏者. 1.好的测试工程师所具备的能力: 细心的观察能力 有效的提问能力 产品的业务能力 好奇心 2.测试人员需要询问问题:测试人员的核心 ...

  9. 什么是单点登录,php是如何实现单点登录的

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...

  10. Mac PyCharm2019激活码

    此教程支持最新2019.2版本Pycharm及其他软件 此教程实时更新,请放心使用:如果有新版本出现猪哥都会第一时间尝试激活: pycharm官网下载地址:http://www.jetbrains.c ...