BZOJ4550 小奇的博弈 【Nimk游戏 + dp + 组合数】
题目
这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色。最左边是白色棋子,最右边
是黑色棋子,相邻的棋子颜色不同。
小奇可以移动白色棋子,提比可以移动黑色的棋子,它们每次操作可以移动1到d个棋子。每当移动某一个棋子时,
这个棋子不能跨越两边的棋子,当然也不可以出界。当谁不可以操作时,谁就失败了。小奇和提比轮流操作,现在
小奇先移动,有多少种初始棋子的布局会使它有必胜策略?
输入格式
共一行,三个数,n,k,d。对于100%的数据,有1<=d<=k<=n<=10000, k为偶数,k<=100。
输出格式
输出小奇胜利的方案总数。答案对1000000007取模。
输入样例
10 4 2
输出样例
182
题解
面对各种数学轰炸。。跪了。
前置知识:
Nimk游戏
Nim游戏基础上,每次可以取之多d堆
先手必败条件:每堆石子转成二进制,各个位的和都为(d + 1)的倍数
例如可以取2次,石子数:111、101、110、011【二进制】
每一位都有2+1=3个1,所以先手必败
本题
黑白棋子相间分布,白棋右移,黑棋左移,每对棋子的间隔长就相当于石子数,而每次可以操作d次,就相当于Nimk游戏
求方案数
一共有K/2堆石子,总数不超过N - K个
首先,总的方案数为C(N,K),我们尝试求出必败的方案数,作差
令f[i][j]表示每堆石子的二进制表示中最高位为i位【从0开始算】,总共有j和石子的方案数
那么有
f[i+1][j+x∗(d+1)∗2i]+=f[i][j]∗C(K/2,x∗(D+1))
原理:最高第i+1位的方案由最高第i位转移而来,每次同时加上(D+1)个1,可枚举x,表示加上x个(D+1)来进行转移,而每次加入x∗(D+1)组石子,又有C(K/2,x∗(D+1))种方法
【模型的转化,dp的应用,组合数的使用】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
using namespace std;
const int maxn = 10005,maxm = 105,INF = 1000000000,P = 1000000007;
LL C[maxn][maxm],f[20][maxn];
int main(){
LL N,K,D;
cin>>N>>K>>D;
for (int i = 0; i <= N; i++){
C[i][0] = 1;
for (int j = 1; j <= i && j <= K; j++)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % P;
}
f[0][0] = 1;
for (LL i = 0; i <= 16; i++)
for (LL j = 0; j <= N - K; j++)
for (LL x = 0; x * (D + 1) <= K / 2 && x * (D + 1) * (1ll << i) + j <= N - K; x++)
f[i + 1][j + x * (D + 1) * (1ll << i)] =
(f[i + 1][j + x * (D + 1) * (1ll << i)] + f[i][j] * C[K/2][x * (D + 1)]) % P;
LL ans = C[N][K];
for (int i = 0; i <= N - K; i++)
ans = (ans - f[16][i] * C[N - K - i + K / 2][K / 2] % P) % P;
cout<<(ans + P) % P<<endl;
return 0;
}
BZOJ4550 小奇的博弈 【Nimk游戏 + dp + 组合数】的更多相关文章
- BZOJ4550: 小奇的博弈(NIMK博弈& 组合数& DP)
4550: 小奇的博弈 Time Limit: 2 Sec Memory Limit: 256 MBSubmit: 159 Solved: 104[Submit][Status][Discuss] ...
- BZOJ2281[Sdoi2011]黑白棋&BZOJ4550小奇的博弈——DP+nimk游戏
题目描述 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小A可以移动白色 ...
- bzoj4550 小奇的博弈
我看出了是个 Nimk 问题.... dp我明白意思,我也会推组合数.... 但是...神tm统计答案啊...蒟蒻不会~
- bzoj 4550: 小奇的博弈【博弈论+dp】
首先看出终止状态是全都堆在左边或者右边,然后发现黑的向左白的向右是最优策略(如果不能这样了也就该输了) 然后就不会了 参考 http://www.cnblogs.com/CQzhangyu/p/770 ...
- 【BZOJ4550】小奇的博弈 博弈论
[BZOJ4550]小奇的博弈 Description 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...
- 【bzoj4550】小奇的博弈 博弈论+dp
题目描述 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边 是黑色棋子,相邻的棋子颜色不同. 小奇可以移动白色棋子,提比可以移动黑色的棋子, ...
- 小奇的仓库(树形DP)
「题目背景」 小奇采的矿实在太多了,它准备在喵星系建个矿石仓库.令它无语的是,喵星系的货运飞船引擎还停留在上元时代! 「问题描述」 喵星系有n个星球,星球以及星球间的航线形成一棵树. 从星球a到星球b ...
- [CSP-S模拟测试]:小奇的矩阵(matrix)(DP+数学)
题目背景 小奇总是在数学课上思考奇怪的问题. 题目描述 给定一个$n\times m$的矩阵,矩阵中的每个元素$a_{i,j}$为正整数.接下来规定: $1.$合法的路径初始从矩阵左上角出发,每 ...
- 【HMOI】小C的填数游戏 DP+线段树维护
[题目描述] 一个长为n的序列,每个元素有一个a[i],b[i],a[i]为0||1,每个点和他相邻的两个点分别有两条边,权值为cost1[i],cost2[i],对于每个区间l,r,我们可以给每一个 ...
随机推荐
- python构造二维列表以及排序字典
1. 构造二维列表: 比如我现在需要一个100*100的二维列表: a = [] for i in range(100): a.append([]) for j in range(100): a[i] ...
- 原lnmp环境服务器升级为mysql+nginx+php单个docker容器构建的lnmp环境
时间:2018年2月 一.项目背景 我单位现web服务架构为lnmp环境,服务器软件.硬件升级部署难:同时开源软件日新月异,考虑到技术升级,领导决定服务器架构整体升级为容器架构,维护性.移植性强. 二 ...
- 渗透测试实验(i春秋 真的很简单)
首先利用给的提示: 所以用户名是 ichunqiu 密码是adab29e084ff095ce3eb 可以确定一般密码都是md5的,但是这个20位 应该去掉ada b29e084ff095ce3e才是正 ...
- c/c++指针传参
首先要理解参数传递,参数传递分值传递,指针传递,引用传递.(就我自己理解,就是把实参对形参进行赋值) 值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值.从被调用函数的角度来说,值传递是单 ...
- Linux硬盘性能检测
对于现在的计算机来讲,整个计算机的性能主要受磁盘IO速度的影响,内存.CPU包括主板总线的速度已经很快了. 基础检测方法 1.dd命令 dd命令功能很简单,就是从一个源读取数据以bit级的形式写到一个 ...
- 用gradle编译任意结构的Android项目
## 需求 * 继续用`Eclipse`项目的结构,但是使用`gradle`编译,或者说任意的项目结构进行编译. ## 解决方案 1. Android studio的项目结构 1. Android S ...
- 系统学习Docker 践行DevOps理念
Docker代表的容器技术是近两年的大热技术,和人工智能.区块链等热点不同,容器技术的门槛并不高,每一个开发.测试.运维人员都能在日常工作中掌握和使用,是当今IT从业人员的必备技能之一.本课程会带大家 ...
- 【java并发编程】十三章:显式锁:LOCK
java5以后,新增了显式锁,用于当内置锁不能满足需求后可选择的一种高级方案. lock接口的特点 与内置锁一样,他能提供互斥性,内存可见性,可重入等特征,与内置锁不同的是,Lock提供了一种无条件, ...
- ipfs01
IPFS音乐播放器 IPFS相关 IPFS第一次亲密接触 什么是IPFS IPFS对比HTTP/FTP等协议的优势 IPFS应用场景 ipfs入门 官网地址:https://ipfs.io 下载安 ...
- 关于c++的头文件依赖
正在看google c++编程规范,里面对头文件依赖是这么说的: 使用前置声明(forward declarations)尽量减少.h文件中#include的数量. 当一个头文件被包含的同时也引入了一 ...