[SDOI2011]黑白棋 kth - nim游戏
题面
题解
观察题目,我们可以发现,这个游戏其实就是不断再把对方挤到一边去,也就是黑子不断往左走,白子不断往右走。
因此可以发现,如果将黑白子按顺序两两配对,那么它们中间的距离会不断缩小,且每次操作只能改变k对黑白子中间的距离,并且每次改变多少没有限制。
那么这就变成了一个kth-nim游戏,因此我们把匹配的黑白子中间的距离当做石子个数,直接按照kth-nim游戏来做即可.
输出方案则要用到DP。
f[i][j]表示DP到二进制的第i位,放j个石头的不合法方案。
那么根据nim游戏,为了保证不合法,我们就要保证二进制上的每一位的1的个数之和整除(k + 1)。
因此我们枚举现在一共已经用了多少个石子,然后枚举当前位(二进制第i位)要用到多少石子。
再用组合数来计算分配方案即可。
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define p 1000000007
#define AC 20100
#define ac 20
#define LL long long
LL n, k, d, ans;
LL fac[AC], inv[AC], f[ac][AC], bits[ac];//f[i][j]表示二进制前i位,放j个石子的方案数
LL C(int x, int y){return fac[x] * inv[y] % p * inv[x - y] % p;}
void up(LL &x, LL y)
{
x += y;
if(x < 0) x += p;
if(x >= p) x -= p;
}
void pre()
{
scanf("%lld%lld%lld", &n, &k, &d);
inv[0] = inv[1] = fac[0] = bits[1] = 1, k >>= 1;//注意0!= 1
int tmp = n + k;
for(R i = 2; i <= tmp; i ++) inv[i] = (p - p / i) * inv[p % i] % p;
for(R i = 1; i <= tmp; i ++) //求出阶乘表和阶乘逆元表
fac[i] = fac[i - 1] * i % p, inv[i] = inv[i] * inv[i - 1] % p;
for(R i = 2; i <= 15; i ++) bits[i] = bits[i - 1] << 1;
}
void work()
{
int maxn = 15, all = n - 2 * k;
f[0][0] = 1;
for(R i = 1; i <= maxn; i ++)
{
for(R j = 0; j <= all; j ++)//枚举当前格子数
{
for(R l = 0; l <= k; l += d + 1)//枚举d + 1的倍数(相比于上次的增量),因为当前位1的个数必须是d + 1的倍数
{//把这l份(d + 1)分配给每一堆石子,但不能拆开任意一堆(不然这个1就不在第i位了)
int have = j - l * bits[i];//上个格子的
if(have < 0) break;//且每堆要么分一个,要么不分,所以份数不能超过堆数
up(f[i][j], f[i - 1][have] * C(k, l) % p);//在k堆里面选l堆出来放
}
}
}//先枚举放了的石子个数,于是就要在剩下的n - i - 2 * k个格子中插入允许相邻的k堆石子 n - i - 2 * k + k = n - i - k
for(R i = 0; i <= all; i ++) up(ans, -C(n - i - k, k) * f[15][i] % p);
up(ans, C(n, k << 1));
printf("%lld\n", ans);
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
//fclose(stdin);
return 0;
}
[SDOI2011]黑白棋 kth - nim游戏的更多相关文章
- Bzoj 2281 [Sdoi2011]黑白棋 题解
2281: [Sdoi2011]黑白棋 Time Limit: 3 Sec Memory Limit: 512 MBSubmit: 592 Solved: 362[Submit][Status][ ...
- 【BZOJ2281】[SDOI2011]黑白棋(博弈论,动态规划)
[BZOJ2281][SDOI2011]黑白棋(博弈论,动态规划) 题面 BZOJ 洛谷 题解 先看懂这题目在干什么. 首先BZOJ上面的题面没有图,换到洛谷看题就有图了. 不难发现都相邻的两个异色棋 ...
- [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
2281: [Sdoi2011]黑白棋 Time Limit: 3 Sec Memory Limit: 512 MBSubmit: 626 Solved: 390[Submit][Status][ ...
- P2490 [SDOI2011]黑白棋
P2490 [SDOI2011]黑白棋 题意 一个 \(1*n\) 的棋盘上,A 可以移动白色棋子,B 可以移动黑色的棋子,其中白色不能往左,黑色不能往右.他们每次操作可以移动 1 到 \(d\) 个 ...
- BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)
题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...
- BZOJ2281[Sdoi2011]黑白棋&BZOJ4550小奇的博弈——DP+nimk游戏
题目描述 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小A可以移动白色 ...
- bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)
黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...
- 【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋
Description 黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是 ...
- [SDOI2011]黑白棋
Description 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...
随机推荐
- python的rtree包缺失libspatiaindex.so
1 准备autoconf工具 yum -y install autoconf automake libtool 2 准备g++编译器 yum -y install gcc gcc-c++ 3 下载并安 ...
- HttpClient使用详解 (一)
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且 ...
- 文件批量加密重命名--python脚本AND mysql命令行导入数据库
在考试中学生交上来的报告,需要进行一下文件名加密,这样阅卷老师就不知道是谁的报告了 在百度帮助下,完成了加密和解密脚本, 加密 #!/usr/bin/python # -*- coding: utf- ...
- 测试面试必会sql(1)
测试一般各种查询语句用的较多,下面的查询语句都是需要熟悉的 Course表 Score表 Student表 Teacher表 1,查询课程编号为“02”的总成绩 SELECT * FROM `Scor ...
- Kibana TypeError : Object #<GlobalState> has no method 'setDefaults'
在windows server中装完elasticsearch和kibana后,elasticsearch能正常访问(http://localhost:9200): 而访问kibana的地址(http ...
- Ubuntu16.04使用Tarball安装ntp
最近在学习linux,看书上例子(鸟哥的linux私房菜 P674),使用Tarball来安装ntp,出了点问题,提示错误,使用 ./configure 来检测程序时,出现如下提示: 提示少了 ope ...
- 4.openldap创建索引
1.索引的意义 提高对Openldap目录树的查询速度 提高性能 减轻对服务器的压力 2.搜索索引 ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn= ...
- C++ 根据图片url 批量 下载图片
最近需要用到根据图片URL批量下载到本地的操作.查找了相关资料,记录在这儿. 1.首先在CSV文件中提取出url ifstream fin("C:\\Users\\lenovo\\Deskt ...
- 1.2Linux下C语言开发基础(学习过程)
===============第二节 Linux下C语言开发基础=========== ********************** 重要知识点总结梳理********************* 一 ...
- struts通配符*的使用
<action name="user_*" class="com.wangcf.UserAction" method="{1}"> ...