2281: [Sdoi2011]黑白棋

Time Limit: 3 Sec  Memory Limit: 512 MB
Submit: 592  Solved: 362
[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 2

Sample Output

182

HINT

1<=d<=k<=n<=10000, k为偶数,k<=100。

Source

  感受到了被博弈论支配的恐惧……

  上来将题意理解为了白棋统一向右走,黑棋统一向左走,只要移动黑白棋就会碰到一起,然后就成了一个裸的nim博弈,然后就没有然后了……

  后来看黄学长的题解领悟到正确思路后默默的跪膜……

  首先我们先确认一下游戏结束的条件,如果A失败就是所有黑白棋都挨在一起且都挤在左侧,反之则都挤在右侧,原理显然。

  那么我们可以发现,如果我们想胜利白棋一定不会向左移,黑棋一定不会向右移,所以,我们可以发现当每一个白棋都和他左边的黑棋碰到一起时游戏实际上就已经结束了。所以,我们可以将相邻的两个棋子配成k/2对,目标实际就转化为了有k/2堆石子一次最少取一个堆里的任意颗石子,最多取d堆里的任意石子。谁先无法行动谁就失败。这就是传说中的nimk模型。(lc:只要你多看几眼论文就会发现这些奇奇怪怪的名词)

  对于nimk模型,先手必败当且仅当对于二进制每一位,如果所有堆的石子数二进制这一位1的和都能被(d+1)整除。

  证明:

    这种“谁不能移谁就输”的游戏先手必败就是当后手可以以某种对称的方式使你每走一步他都可以走一步实质完全一样的与你对应。表现在这道题里就是当你在二进制里的第i位取x个1时,他只要取d+1-x个就好了。

  不过这道题我们并不是要去判断是否合法, 而是计算方案数。

  为了方便,我们可以通过融斥去求答案。我们设f[i][j]为考虑了所有堆二进制前i位,已经在堆里面一共放了j个石子的方案数。转移方程即为:f[i+1][j+k*(d+1)*(1<<i)]+=f[i][j]*C(K/2,k*(d+1))。这里的K我指的是题目中的k,k*(d+1)就是枚举一共放多少组,C(K/2,k*(d+1))代表究竟放到哪一堆里。最后累加的时候记得再算上我们剩余的石子的摆放数,最终拿C(n,k)减去不合法方案数即可。

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 10005
using namespace std;
int n,m,d,p=;
long long ksm(long long a,long long z)
{
long long ans=;
while(z)
{
if(z&) ans*=a,ans%=p;
a*=a;
a%=p;
z>>=;
}
return ans;
}
long long jc[N],ni[N];
long long get_c(int x,int y)
{
return ((jc[x]*ni[y]%p)*ni[x-y]%p)%p;
}
long long f[][N];
int main()
{
scanf("%d%d%d",&n,&m,&d);
if(m==)
{
printf("%lld\n",1ll*(n-)*(n-)/);
exit();
}
jc[]=ni[]=;
for(int i=;i<=n;i++) jc[i]=(jc[i-]*i)%p;
ni[n]=ksm(jc[n],p-);
for(int i=n-;i;i--) ni[i]=ni[i+]*(i+)%p;
f[][]=;
for(int i=;i<=;i++)
{
for(int j=;j<=n-m;j++)
{
for(int k=;j+(d+)*k*(<<i)<=n-m&&(d+)*k<=m/;k++)
{
f[i+][j+(d+)*k*(<<i)]+=f[i][j]*get_c(m/,k*(d+));
f[i+][j+(d+)*k*(<<i)]%=p;
}
}
}
long long ans=;
for(int i=;i<=n-m;i++)
ans+=f[][i]*get_c(n-i-m/,m/)%p,ans%=p;
printf("%lld\n",(get_c(n,m)-ans+p)%p);
return ;
}

Bzoj 2281 [Sdoi2011]黑白棋 题解的更多相关文章

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

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

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

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

  3. BZOJ 2281: [Sdoi2011]黑白棋(dp+博弈论)

    传送门 解题思路 首先发现可以把相邻的黑白棋子之间的距离看成一堆棋子,那么这个就可以抽象成\(Nim\)游戏每次可以取\(d\)堆这个游戏,而这个游戏的\(SG\)值为\(x\%(d+1)\),那么题 ...

  4. bzoj 2281: [Sdoi2011]黑白棋

    再次,,,,,虚(一开始看错题了,看成一次移动一个棋子,能移动1-d个格子...这样的话有没有大神会做??本蒟蒻就教) 额,,直接%%%%把...http://hzwer.com/5760.html ...

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

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

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

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

  7. P2490 [SDOI2011]黑白棋

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

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

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

  9. [SDOI2011]黑白棋

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

随机推荐

  1. WPF 鼠标在图片Image上悬停时切换更改设置图片源Source

    // 无效的写法,图片不会被切换 <Image Margin="0,0,0,0" Width="50" Height="50" Sou ...

  2. select ,update 加锁

    最近我在弄一个项目,其中涉及到了数据批量导入数据库的过程,在导入数据的时候,每一条数据会生成一个唯一标识,但是我发现有些数据的标识重复了.我在网上查了一下说这是“数据库 并发性”的问题解决方案,上锁. ...

  3. C# 委托参数方法实例

    /// <summary> /// 方法委托 /// </summary> /// <param name="dwEnrollNum">< ...

  4. visual studio 2017 添加MSDN

    原文:visual studio 2017 添加MSDN 1.启动VS2017的安装软件,点击更改,进行MSDN帮助组件添加安装. 2.在单个组件中找到"Help Viewer", ...

  5. 反射:获取枚举类型的Name,Value,Description

    [Obsolete("请使用新的方法XXX")] //使用Obsolete特性来告诉使用者这是一个过期的方法 private static void Test() { Type t ...

  6. 使用Microsoft Power BI进行基本的数据分析

    Power BI是微软开发的一款简单易用的数据可视化软件. 导入数据 使用Power BI的第一步是将数据导入到软件中.获取数据->更多,可以看到可使用多种数据源,甚至微软提供了一些联机的数据源 ...

  7. Delphi中动态调用TXMLDocument的经历

    var  vXMLDocument: TXMLDocument;begin  vXMLDocument := TXMLDocument.Create('c:/temp/temp.xml');  Cap ...

  8. Delphi使用TObject类对象创建接受window消息(使用Classes.AllocateHWnd为对象创建一个尺寸为0的窗口,从而有了Handle)good

    在delphi中,有时候我们希望对象可以接收windows消息,怎么办呢?因为要接收windows消息起码要有windows Handle,难道要建立的一个可见窗口?那样似乎太差强人意了.delphi ...

  9. qtextedit中的光标问题(通过调用repaint去掉Focus的阴影)

    [问题]两个textedit,取名为view0,view1.实现view0输入固定的字符个数后,用setFocus切换聚焦到view1,但是切换完了之后view0还会保留光标残影,出现两个文本框中都有 ...

  10. DIOCP3 DEMO的编译(去掉VCL前缀)

    总有些朋友问我,关于DEMO编译的一些问题,每次都回答大概都差不多,我想还是写篇说明书给大家,关于DEMO编译的步骤. [环境设定] 1.将DIOCP3\source路径添加到Delphi的搜索路径, ...