[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个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...
随机推荐
- jsp命名规则
jsp也用驼峰规则命名即可,不要使用下划线,否则在tomcat中容易出现解析错误
- 【MYSQL安装】mysql 5.6在centos6.4上的安装
1.卸载系统自带的mysql [root@zhangmeng ~]# rpm -qa |grep mysql mysql-libs--.el6_3.x86_64 [root@zhangmeng ~]# ...
- ConfigurationProperties cannot be resolved to a type
pom.xml 中报错之前: <parent> <groupId>org.springframework.boot</groupId> <artifactId ...
- Linux中如何安装Apache服务器
Linux中如何安装Apache服务器 由于学习的需要,所有手动安装了一下Apache源码包,安装过程中的问题千奇百怪,但是如果弄清楚了问题出在哪里,那么也不是太难.如果有学习者出现安装中的问题,可仔 ...
- PHP版本的讲解
原文地址:http://dev.meettea.com/show-90-1.html 最近发现很多PHP程序员对PHP版本知识了解不是很清楚,其中不乏PHP产品主力开发人员. PHP版本主要分三支:P ...
- Lua学习笔记(6): 函数
Lua的函数 函数用于简化程序,当某些工作需要重复执行的时候就可以使用函数减轻工作量(虽然复制粘贴也行) 语法: function 函数名(参数列表) 函数体 return 返回值 end --结束标 ...
- POJ-3122(二分算法)
//题意:这是一个分蛋糕的游戏, t个测试数据,输入n, f n代表的是n块蛋糕,蛋糕的高为1, f代表的是f个人朋友,然后输入每份蛋糕的半径 // 将n块蛋糕分成 f+1 份 每一份都是完成的一块蛋 ...
- MongoDB开启权限认证
MongoDB默认安装完后,如果在配置文件中没有加上auth = true,是没有用户权限认证的,这样对于一个数据库来说是相对不安全的,尤其是在外网的情况下. 接下来是配置权限的过程: //切入到 ...
- lxd&openstack-lxd源码剖析
lxd:https://linuxcontainers.org/lxd/,目标是融入到openstack体系被管理,像虚拟机一样被管理使用.从如下图可知,并非走的是libvirt-lxc路线,而是no ...
- python实现lower_bound和upper_bound
由于对于二分法一直都不是很熟悉,这里就用C++中的lower_bound和upper_bound练练手.这里用python实现 lower_bound和upper_bound本质上用的就是二分法,lo ...