[BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
2281: [Sdoi2011]黑白棋
Time Limit: 3 Sec Memory Limit: 512 MB
Submit: 626 Solved: 390
[Submit][Status][Discuss]Description
小A和小B又想到了一个新的游戏。这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色。最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同。小A可以移动白色棋子,小B可以移动黑色的棋子,他们每次操作可以移动1到d个棋子。每当移动某一个棋子时,这个棋子不能跨越两边的棋子,当然也不可以出界。当谁不可以操作时,谁就失败了。小A和小B轮流操作,现在小A先移动,有多少种初始棋子的布局会使他胜利呢?Input
共一行,三个数,n,k,d。Output
输出小A胜利的方案总数。答案对1000000007取模。
Sample Input
10 4 2Sample Output
182HINT
1<=d<=k<=n<=10000, k为偶数,k<=100。
Source
很有意思的一道博弈题,可惜HZWER学长给出了反例。
那么这一题通过手玩可以发现,最终状态必定是所有棋子全部扎堆在棋盘左端或右端,棋子之间没有间隙。不过仔细观察可以发现,可能在游戏状态中会出现所有棋子扎堆但不在棋盘一端的情况,其实那个时候就已经决定了最终的胜负。因为只要一方朝自己来的方向走了,则另一方必定能也往那边走一步,最终会步步紧逼直到走到棋盘一端。
根据这一点,感性理解一下,这个游戏就是一个把对方棋子“怼”过去的过程,谁怼赢了就是胜者。所以从一开始双方都一定拼尽全力往对面怼,所以有一个结论:先手不可能往左走,后手不可能往右走。
这样这个问题就变成了一个取石子游戏,每对相邻的白子和黑子之间的格子数是石子数(显然共有K/2堆石子),每人每次选不超过k堆取一个石子。
这个问题叫K-Nim,结论是:将所有石子数转成二进制,如果对于每一位二进制,这一位上为1的石子堆数都能被k+1整除则为必败态,否则为必胜态。
证明主要思路是: 1.最终态二进制每一位都为0必为必败态。2.只要有某位的1的个数不被k+1整除,则必然有一种走法使每一位都被整除。 3.如果每一位都被k+1整除,则无论怎么走都不可能使得每一位都仍然能被整除。
这三点分别保证了:最终态是必败态。必胜态必定能走到必败态。必败态只能走到必胜态。
详细证明:http://blog.csdn.net/weixinding/article/details/7321139
这样,我们分别用了“寻找最终态”和“模仿”的技巧将问题转化为了K-Nim问题。回到这一题,最终答案=总方案数-必败态的方案数。
设$f_{i,j}$表示前$i$个二进制位共放了$j$个石子的方案数,则$$ans=C_n^K-\sum_{i=0}^{n-K} f_{s,i}*C_{n-i-K/2}^{K/2}$$s为最高位的1,这里取15就够了。
考虑$f$的转移方程即可:$$f_{i+1,j+k*(d+1)*(1<<i)}\ \ +=\ \ f_{i,j}*C_{K/2}^{k*(d+1)}$$
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const ll N=,mod=;
ll tot,ans,bin[],c[N][],f[][N];
int n,K,d,p; void add(ll &x,ll y){ x=(x+y)%mod; }
void pre(){
rep(i,,n) c[i][]=;
rep(i,,n) rep(j,,min(*K,i)) c[i][j]=(c[i-][j]+c[i-][j-])%mod;
}
int C(int n,int m){ if (m>n-m) m=n-m; return c[n][m]; } int main(){
freopen("bzoj2281.in","r",stdin);
freopen("bzoj2281.out","w",stdout);
bin[]=; rep(i,,) bin[i]=bin[i-]<<;
scanf("%d%d%d",&n,&K,&d); K>>=;
pre(); f[][]=;
rep(i,,) rep(j,,n-*K)
for (int k=; k*(d+)<=K && j+k*(d+)*bin[i]<=n-*K; k++)
add(f[i+][j+k*(d+)*bin[i]],f[i][j]*C(K,k*(d+)));
rep(i,,n-*K) add(ans,f[][i]*C(n-i-K,K));
tot=C(n,K*); printf("%lld\n",(tot-ans+mod)%mod);
return ;
}
[BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)的更多相关文章
- BZOJ2281[Sdoi2011]黑白棋&BZOJ4550小奇的博弈——DP+nimk游戏
题目描述 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小A可以移动白色 ...
- BZOJ2281:[SDOI2011]黑白棋(博弈论,组合数学,DP)
Description 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...
- [SDOI2011]黑白棋 kth - nim游戏
题面 题面 题解 观察题目,我们可以发现,这个游戏其实就是不断再把对方挤到一边去,也就是黑子不断往左走,白子不断往右走. 因此可以发现,如果将黑白子按顺序两两配对,那么它们中间的距离会不断缩小,且每次 ...
- BZOJ2281 [SDOI2011]黑白棋 【dp + 组合数】
题目 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小A可以移动白色棋子 ...
- bzoj2281 [Sdoi2011]黑白棋
一眼$nimk$游戏,后来觉得不对劲,看了黄学长博客发现真的不是$nimk$. 就当是$nimk$做吧,那么我们要保证每一位上一的个数都是$d+1$的倍数. $dp$:$f[i][j]$表示从低到高第 ...
- 【BZOJ2281】[SDOI2011]黑白棋(博弈论,动态规划)
[BZOJ2281][SDOI2011]黑白棋(博弈论,动态规划) 题面 BZOJ 洛谷 题解 先看懂这题目在干什么. 首先BZOJ上面的题面没有图,换到洛谷看题就有图了. 不难发现都相邻的两个异色棋 ...
- Bzoj 2281 [Sdoi2011]黑白棋 题解
2281: [Sdoi2011]黑白棋 Time Limit: 3 Sec Memory Limit: 512 MBSubmit: 592 Solved: 362[Submit][Status][ ...
- P2490 [SDOI2011]黑白棋
P2490 [SDOI2011]黑白棋 题意 一个 \(1*n\) 的棋盘上,A 可以移动白色棋子,B 可以移动黑色的棋子,其中白色不能往左,黑色不能往右.他们每次操作可以移动 1 到 \(d\) 个 ...
- bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)
黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...
随机推荐
- 【BZOJ】3238: [Ahoi2013]差异
[题意]给定长度为n的小写字母字符串,令Ti表示以i开头的后缀,求Σ[Ti+Tj-2*lcp(Ti,Tj)],1<=i<j<=n. [算法]后缀自动机 [题解]Σ(Ti+Tj)只与n ...
- 【leetcode 简单】第九题 移除元素
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...
- JFinal向客户端渲染图片的方法
JFinal提供了好几种方便的render但是不知道为啥就是没有提供直接渲染图片的render,如果我们直接在Controller的方法中往输入流中写的话是还是会有默认的render生效的,比如下面这 ...
- Entity Framework(EF的Database First方法)
EntityFramework,是Microsoft的一款ORM(Object-Relation-Mapping)框架.同其它ORM(如,NHibernate,Hibernate)一样, 一是为了使开 ...
- http之100-continue
[http之100-continue] 1.http 100-continue用于客户端在发送POST数据给服务器前,征询服务器情况,看服务器是否处理POST的数据,如果不处理,客户端则不上传POST ...
- css 水平、垂直居中
水平居中 行内元素 行内元素:(img.span.文字等行内元素),通过在父级元素设置 text-align:center 使元素水平居中. 块级元素 块级元素:(div.p.h1...h6.ul.l ...
- java并发-同步容器类
java平台类库包含了丰富的并发基础构建模块,如线程安全的容器类以及各种用于协调多个相互协作的线程控制流的同步工具类. 同步容器类 同步容器类包括Vector和Hashtable,是早期JDK的一部分 ...
- 查找内容grep命令
标准unix/linux下的grep通过以下参数控制上下文 grep -C 5 foo file 显示file文件中匹配foo字串那行以及上下5行 grep -B 5 foo file 显示foo及前 ...
- 关于wordpress插件WP SMTP的邮箱设置
花了两天的时间把邮箱设置好了,把大概的步骤写下,放一下查到的资料. 1.去域名服务商那里添加MX记录 如下图的MX 2.测试主机是否禁用了mail()函数 参考链接wo ...
- **CodeIgniter通过hook的方式实现简单的权限控制
根据自己的实际情况,需要两个文件,一个是权限控制类,Acl,另外一个是权限配置的文件acl.php放在了config这个目录下. Acl这个类放在了application/hook/acl.php.通 ...