BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)
怎么SDOI2011和SDOI2019的两道题这么像啊。。(虽然并不完全一样)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2281
(luogu) https://www.luogu.org/problemnew/show/P2490
题解: 博弈论好难啊完全学不来QAQ
题目里应该有个限制,是先手不能左移,后手不能右移。
简单转化一发,就相当于有\(n\)堆石子,每次从\(1\)到\(d\)堆中取走任意多个,最后取完的人输。
其实这就是个Nim博弈套Bash博弈。
然后……然后我就不会了。
按理说……\(d=1\)的时候异或和为\(0\), 也就是每个二进制位\(1\)的个数为偶数,那么这个不是连猜都能猜出来每个二进制位\(1\)的个数为\((d+1)\)的倍数吗……Nim博弈套Bash博弈啊……
然后感性理解一下(可能也能算个证明吧): 考虑\(d=1\) Nim游戏的正确性,显然异或和为\(0\)时先手能且仅能将其变为不为\(0\),而后手在这之后能将其变为为\(0\). 假设先手动的最高位为\(i\), 则后手动第\(i\)位上为\(1\)的另一个石子,下面的变成与之对应的即可。归纳可证。那么考虑\(d>1\), 当所有数出现次数均为\((d+1)\)的倍数时,先手不可能依然变为出现次数均为\((d+1)\)的倍数;从高到低考虑位\(j\), 设现在已经改变的堆数为\(t\),\(t\)个数中有\(a\)个在位\(j\)上为\(1\), \(b\)个为\(0\), 并假设后手改动前这一位上\(1\)的个数模\((d+1)\)总共是\(x\). 若\(a\ge x\), 则改变这\(a\)个中的\(x\)个即可;若\(b\ge d+1-x\)则可以把\(b\)个中的\((d+1-x)\)个从\(0\)变成\(1\); 否则另外选择\(t\)堆之外的\((x-a)\)堆变成\(1\), 则选的总数为\((x-a)+a+b=x+b\le d+1-b+b=d+1\), 故移动依然合法。(怎么写着写着就变成抄别的题解了……)
然后问题转化为求\(m\)个数和为\(n\)二进制每一位\(1\)的个数都为\((d+1)\)的倍数的方案数。(计数我也不会啊呜呜呜……)
设\(dp[i][j]\)表示考虑二进制低\(i\)位,和为\(j\)的方案数,随便枚举一下转移即可
时间复杂度很低。
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#define llong long long
using namespace std;
inline int read()
{
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x;
return -x;
}
const int P = 1e9+7;
const int N = 2e4;
const int LGN = 14;
llong fact[N+3],finv[N+3];
llong dp[LGN+3][N+3];
int n,m,d;
llong quickpow(llong x,llong y)
{
llong cur = x,ret = 1ll;
for(int i=0; y; i++)
{
if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
cur = cur*cur%P;
}
return ret;
}
llong comb(llong x,llong y) {return x<0||y<0||x<y ? 0ll : fact[x]*finv[y]%P*finv[x-y]%P;}
int main()
{
fact[0] = 1ll; for(int i=1; i<=N; i++) fact[i] = fact[i-1]*i%P;
finv[N] = quickpow(fact[N],P-2); for(int i=N-1; i>=0; i--) finv[i] = finv[i+1]*(i+1)%P;
scanf("%d%d%d",&n,&m,&d); n-=m; m>>=1;
for(int i=0; i*(d+1)<=m && i*(d+1)<=n; i++)
{
dp[0][i*(d+1)] = comb(m,(d+1)*i);
}
for(int i=1; i<=LGN; i++)
{
for(int j=0; j<=n; j++)
{
llong cur = dp[i-1][j];
if(cur)
{
for(int k=0; j+(d+1)*k*(1<<i)<=n && (d+1)*k<=m; k++)
{
llong tmp = cur*comb(m,(d+1)*k);
dp[i][j+(d+1)*k*(1<<i)] = (dp[i][j+(d+1)*k*(1<<i)]+tmp)%P;
}
}
}
}
llong ans = 0ll;
for(int i=0; i<=n; i++)
{
llong tmp = comb(n+m-i,m)*dp[LGN][i];
ans = (ans+tmp)%P;
}
ans = (comb(n+m+m,m+m)-ans+P)%P;
printf("%lld\n",ans);
return 0;
}
BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)的更多相关文章
- P2490 [SDOI2011]黑白棋
P2490 [SDOI2011]黑白棋 题意 一个 \(1*n\) 的棋盘上,A 可以移动白色棋子,B 可以移动黑色的棋子,其中白色不能往左,黑色不能往右.他们每次操作可以移动 1 到 \(d\) 个 ...
- BZOJ2281:[SDOI2011]黑白棋(博弈论,组合数学,DP)
Description 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...
- luoguP2490 [SDOI2011]黑白棋 博弈论 + 动态规划
博弈部分是自己想出来的,\(dp\)的部分最后出了点差错QAQ 从简单的情况入手 比如\(k = 2\) 如果有这样的局面:$\circ \bullet $,那么先手必输,因为不论先手怎样移动,对手都 ...
- BZOJ2281 [SDOI2011]黑白棋 【dp + 组合数】
题目 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小A可以移动白色棋子 ...
- 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][ ...
- bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)
黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...
- BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)
题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...
随机推荐
- Css设置最优先
input{ width: 220px !important; } css中 加上 !important 用一些前端框架,源文件修改不便时 可以这样用
- Spring(十)--Advisor顾问
Spring之Advisor顾问 1. 创建新的xml文件 advisor.xml <!--01. 配置目标对象 实际肯定是配置UserServiceImpl--> <bean i ...
- Luogu P1450 [HAOI2008]硬币购物
题目 一个很自然的想法是容斥. 假如只有一种硬币,那么答案就是没有限制的情况下买\(s\)的方案数减去强制用了\(d+1\)枚情况下买\(s\)的方案数即没有限制的情况下买\(s-c(d+1)\)的方 ...
- MyBatis时间排序问题
在数据中create_time字段是DateTime类型, 逆向工程后实体类中对应的成员变量类型为Date 时间排序代码为: 测试结果: 时间排序错乱. 解决方法: 1,在数据库创建varchar类型 ...
- Nginx与PHP如何协同工作
要说Nginx与PHP如何协同工作,首先得说CGI和FastCGI两个协议. CGI是Web Server与后台语言交互的协议,有了这个协议,开发者可以使用任何语言处理Web Server发来的请求, ...
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 H. Skiing
题意:在这个寒假中,鲍勃有计划在山区度假胜地滑雪.这个滑雪胜地有M个不同的滑雪道和N个不同的标志位于那些转弯处点.从第S标记到第T标志的第i路径具有长度L.每个路径必须遵循降低高度的原则,起点必须严格 ...
- 09、RNA降解图的计算过程
RNA降解是影响芯片质量的一个很重要的因素,因为RNA是从5’开始降解的,所以理论5’的荧光强度要低于3’.RNA降解曲线可以表现这种趋势. 以样品GSM286756.CEL和GSM286757.CE ...
- 学会这些 pycharm 编程小技巧,编程效率提升 10 倍
PyCharm 是一款非常强大的编写 python 代码的工具.掌握一些小技巧能成倍的提升写代码的效率,本篇介绍几个经常使用的小技巧. 一.分屏展示 当你想同时看到多个文件的时候: 1.右击标签页: ...
- 吴恩达深度学习:2.15python中的广播
1.Broadcasting example (1)下面矩阵描述了来自四种不同的100克碳水化合物,蛋白质和脂肪的卡路里数量 比如说100g苹果所含的热量有56克来自碳水化合物,相比之下来自蛋白质和脂 ...
- 剑指offer-3:跳阶梯
三.跳台阶 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 分析 青蛙每一次跳跃只有两种选择:一是再跳1级阶梯到达第n ...