P2490 [SDOI2011]黑白棋

题意

一个 \(1*n\) 的棋盘上,A 可以移动白色棋子,B 可以移动黑色的棋子,其中白色不能往左,黑色不能往右。他们每次操作可以移动 1 到 \(d\) 个棋子。

每当移动某一个棋子时,这个棋子不能跨越两边的棋子,当然也不可以出界。当谁不可以操作时,谁就失败了。

思路

显然可以将题意转化为一种 K-Nim 游戏,即在 \(\frac k2\) 堆石子中,每次可将 \(d\) 堆石子取任意个,令对手无路可走时获胜。

用总方案数减去先手必败的方案数即为答案,因为先手必败方案更加好算。


K-Nim 游戏

结论

设 \(r_i\) 为二进制第 \(i\) 位所有数该位为 1 的个数 \(\pmod {d+1}\) 的值,那么只用一步即可在 “\(r\) 全为 0” 和 “\(r\) 不全为 0” 两种状态间转移。

感性证明

考虑一个大小不超过 \(d\) 的集合,为我们一次操作需要拿走的石子堆的集合,选 0 或 1 都是合法的。

假设我们现在已经有这样一个大小为 \(d\) 的集合,其中有 \(x\) 个 1,\(y\) 个 0,即 \(x+y=d\)。我们要让 \(r\) 等于零,分以下情况:

  • \(x\ge r\) 则选择 \(r\) 个 1 变为 0 即可。
  • \(x<r\) 则 \(y+r\ge d+1\) ,则选择 \(d-r+1\) 个 0 变为 1 即可。

所以一定有一种方法使这一位的 \(r\) 变成 0.

现在我们并没有一个可以随便转换的集合,但是当一个数的高位从 1 变为 0 之后低位就可以随便选 0 和 1.所以我们从高位向低位考虑,如果一直符合第二个情况就向下考虑,否则就是第一个情况,并且在这种情况下把 1 变成 0 是合法的,那么我们扩大集合即可。

得证。


在上述博弈中,所有 \(r\) 为 0 的状态是必败态。我们只需要算所有这种情况的方案就可以了。

考虑 Dp。设 \(f_{ij}\) 为前 \(i\) 位的 \(r\) 均为 0,总共 \(j\) 个石子的方案数。

新选一位,枚举在 \(d+1\) 堆石子中放入若干次石子。即

\[f_{i+1,j+2^ix(d+1)}+=f_{i,j}\binom{\frac k2}{x*(d+1)}
\]

最后统计答案需要枚举每一堆的起点位置,即在原题中的白棋的位置,答案为所有位的

\[f_{i,j}\binom{n-j-\frac k2}{\frac k2}
\]

的和。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=x*10+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=10005,mod=1e9+7;
int n,k,d,C[maxn][205],f[18][100005];
inline void work(){
n=read(),k=read(),d=read();
C[0][0]=1;
for(int i=1;i<=n;i++){
C[i][0]=1;
for(int j=1;j<=200;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
f[0][0]=1;
for(int i=0;i<=16;i++) for(int j=0;j<=n-k;j++) for(int x=0;(1ll<<i)*x*(d+1)<=n-k and x*(d+1)<=k/2;x++)
f[i+1][j+(1ll<<i)*x*(d+1)]=(f[i+1][j+(1ll<<i)*x*(d+1)]+1ll*f[i][j]*C[k/2][x*(d+1)])%mod;
int ans=0;
for(int i=0;i<=n-k;i++) ans=(ans+1ll*f[17][i]*C[n-i-k/2][k/2])%mod;
printf("%d\n",(C[n][k]-ans+mod)%mod);
}
}
signed main(){
star::work();
return 0;
}

P2490 [SDOI2011]黑白棋的更多相关文章

  1. BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)

    怎么SDOI2011和SDOI2019的两道题这么像啊..(虽然并不完全一样) 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?i ...

  2. 【BZOJ2281】[SDOI2011]黑白棋(博弈论,动态规划)

    [BZOJ2281][SDOI2011]黑白棋(博弈论,动态规划) 题面 BZOJ 洛谷 题解 先看懂这题目在干什么. 首先BZOJ上面的题面没有图,换到洛谷看题就有图了. 不难发现都相邻的两个异色棋 ...

  3. [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)

    2281: [Sdoi2011]黑白棋 Time Limit: 3 Sec  Memory Limit: 512 MBSubmit: 626  Solved: 390[Submit][Status][ ...

  4. Bzoj 2281 [Sdoi2011]黑白棋 题解

    2281: [Sdoi2011]黑白棋 Time Limit: 3 Sec  Memory Limit: 512 MBSubmit: 592  Solved: 362[Submit][Status][ ...

  5. bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)

    黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...

  6. 【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋

    Description 黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是 ...

  7. [SDOI2011]黑白棋

    Description 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...

  8. BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)

    题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...

  9. 【bzoj2281】 Sdoi2011—黑白棋

    http://www.lydsy.com/JudgeOnline/problem.php?id=2281 (题目链接) 题意 一个1*n的棋盘,棋盘上一个隔一个的放着个黑棋和白棋,最左端是白棋,最右端 ...

随机推荐

  1. Python_Selenium之basepage 识别元素、浏览器操作、获取属性、鼠标事件、键盘事件、弹窗、切换frame、切换句柄等封装

    #coding=gbkimport osimport timefrom selenium import webdriverfrom selenium.webdriver.common.by impor ...

  2. java后端知识点梳理——Redis

    redis都支持哪些数据类型?应用场景有哪些? redis支持五种数据类型作为其Value,redis的Key都是字符串类型的. string:redis 中字符串 value 最大可为512M.可以 ...

  3. MySQL8性能优化

    MySQL8.0 引擎: 来看看MySQL8提供的引擎: 常用引擎: InnoDB:支持事务,行级锁,外键,崩溃修复,多版本并发控制:读写效率相对较差,内存使用相对较高,占用数据空间相对较大. MyI ...

  4. Zab协议 (史上最全)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  5. perror()函数的使用

    perror()函数的功能是打印一个系统错误信息.        perror()函数在Linux系统中属于库函数,在头文件中有如下定义: #include <stdio.h>       ...

  6. 安装redHat6.5详细图文教程

    ​ ​ 进入VM虚拟机,双击进入已经创建好的红帽6虚拟机 双击进入CD/DVD,准备添加红帽6.5的iso镜像文件 [红帽6.5的iso镜像文件需要先下载,redhat_6.5下载地址:https:/ ...

  7. 使用python脚本统一重命名训练图片文件名

    Yolo算法,在进行模型训练时,常常使用VOC数据格式. 将图片文件复制到JPEGImages目录下,需要对文件名进行VOC标准格式编号重命名,如2020_000001.jpg,2020_000002 ...

  8. Golang中GBK和UTF8编码格式互转

    Golang中GBK和UTF8编码格式互转 需求 已知byte数组的编码格式转换 实现代码 package utils import ( "bytes" "golang. ...

  9. 『心善渊』Selenium3.0基础 — 10、使用Seleniun定位页面元素归纳总结(超详细)

    目录 1.Selenium中8种基本元素定位方式 (1)单数形式 (2)复数形式 2.By类定位的8种定位方式 (1)单数形式 (2)复数形式 3.XPath定位总结 (1)基础定位语法 (2)属性定 ...

  10. 温故知新,.Net Core遇见Postman(API Development),进阶分布式微服务高效调式

    什么是Postman 环境变量(Environments) 全局协议 描述 变量 初始值 当前值 请求协议 request_protocol http http 授权信息 描述 变量 初始值 当前值 ...