●BZOJ 1272 [BeiJingWc2008]Gate Of Babylon
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=1272
题解:
容斥,Lucas定理
本题的容斥考虑类似 [BZOJ 1042 [HAOI2008]硬币购物]
即 ANS = 至少 0 种超级神器超过数量限制的方案数
-至少 1 种超级神器超过数量限制的方案数
+至少 2 种超级神器超过数量限制的方案数
-...+...
那么就下来就需要解决两个问题:
1).如果随便选的话,如何求出方案数?
假设需要从 N 种任意宝具里选出不超过 m 个,求法如下:
先考虑必须选 m 个:
这是一个典型的组合问题:
即要把 m 个相同的小球放到 N 个盒子里,且盒子可以为空,求方案数。
则方案数为 ${C}_{N+m-1}^{N-1}$。
怎么理解呢? 可以叫做 "插隔板法" 吧。
如果现在有 N+m-1 个位置,我们可以在 N-1 个位置放隔板,
并且令相邻的两个隔板(把首尾也看作另外2个隔板)中间的空余位置放小球。
(相邻的两个隔板之间共有 N 个间隙,所以可以把每个间隙依次看做一个盒子。)
则任意一种插隔板的方法都对应一种把小球放入盒子的方法。
所以,方案数为 ${C}_{N+m-1}^{N-1}$
但是这是必须选m个的方案数。
所以需要把下面东西加起来才是选的物品不超过 m个 的方案数
${W=}{C}_{N-1}^{N-1}+{C}_{N}^{N-1}+{C}_{N+1}^{N-1}+\cdots+{C}_{N+m-1}^{N-1}$
然后需要化简这个式子:由一个小性质 : ${C}_{i-1}^{j}+{C}_{i-1}^{j-1}={C}_{i}^{j}$
所以 ${W} = {W} + {C}_{N-1}^{N} – {C}_{N-1}^{N}$
然后就可以从前面一直结合到末尾,得到
${W} = {C}_{N+m}^{N} – {C}_{N-1}^{N}$,但是 ${C}_{N-1}^{N}={0}$
所以 ${W} = {C}_{N+m}^{N}$
然后第一个问题就这么愉快地解决了。
(哦,还有,这个组合数的 N,M都太大了但模数 P 很小,需要用到Lucas定理,不会的快百度百科一下!)
2).如何求出那些用于容斥的方案数呢?
考虑将一些超级神器强制超过使用其限制的个数(设超出的总个数为 k),
那么在接下来,在 N 种宝具里任意选出不超过剩下的 m=M-k 个物品的方案都为非法方案,
而这个方案数就可以用第一个问题的解决方法去求解。
所以具体做法就是枚举一个集合 S表示该集合里的超级神器会被强制使用超过使用其限制的个数,
然后求出该情况下的方案数后,对应着本文开篇的容斥式子去加加减减就好啦。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define _ % P
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
int B[100500],h[100500],k[100500],fac[100500],inv[100500];
int N,T,M,P,ANS;
int pow(int a,int b){
int ret=1;
while(b){
if(b&1) ret=(1ll*ret*a)_;
a=(1ll*a*a)_; b>>=1;
}
return ret;
}
int C(int n,int m){
if(n<m) return 0;
return 1ll*fac[n]*inv[m]_*inv[n-m]_;
}
int Lucas(int n,int m){
int ret=1;
while(m){
ret=(1ll*ret*C(n%P,m%P))_;
n/=P; m/=P;
}
return ret;
}
int main()
{
scanf("%d%d%d%d",&N,&T,&M,&P); fac[0]=inv[0]=1;
for(int i=1;i<P;i++) fac[i]=(1ll*fac[i-1]*i)_;
inv[P-1]=pow(fac[P-1],P-2);
for(int i=P-2;i;i--) inv[i]=(1ll*inv[i+1]*(i+1))_;
for(int i=1;i<=T;i++) scanf("%d",&B[1<<(i-1)]);
for(int s=1,q;q=(s&-s),s<(1<<T);s++)
k[s]=1ll*k[s^q]+B[q]+1,
h[s]=h[s^q]+1;
for(int s=0,m,tmp;s<(1<<T);s++){
m=M-k[s]; if(m<0) continue;
tmp=Lucas(N+m,N);
if(h[s]&1) tmp=(-1ll*tmp+P)_;
ANS=((1ll*ANS+tmp)_+P)_;
}
printf("%d",ANS);
return 0;
}
●BZOJ 1272 [BeiJingWc2008]Gate Of Babylon的更多相关文章
- bzoj 1272: [BeiJingWc2008]Gate Of Babylon
Description Solution 如果没有限制,答案就是 \(\sum_{i=0}^{m}C(n+i-1,i)\) 表示枚举每一次取的个数,且不超过 \(m\),方案数为可重组合 发现这个东西 ...
- 【BZOJ 1272】 1272: [BeiJingWc2008]Gate Of Babylon (容斥原理+卢卡斯定理)
1272: [BeiJingWc2008]Gate Of Babylon Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 254 Solved: 12 ...
- BZOJ1272: [BeiJingWc2008]Gate Of Babylon
题解: 多重集合的组合数?还是0-m?有些元素有个数限制? 多重集合的组合数可以插板法,0-m直接利用组合数的公式一遍求出来,个数限制注意到只有15个,那我们就暴力容斥了 AC了真舒畅.. 注意开lo ...
- [BeiJingWc2008]Gate Of Babylon
<基尔伽美修>是人类历史上第一部英雄史诗,两河流域最杰出的文学作品之一.作品讲述了基尔伽美修一生的传奇故事.在动画Fate/staynight中,基尔伽美修与亚瑟王等传说中的英雄人物一起出 ...
- 【BZOJ】【1272】【BeiJingWC2008】Gate of Babylon
组合数学+容斥原理 Orz zyf-zyf 多重集组合数0.0还带个数限制? ——> <组合数学>第6章 6.2带重复的组合 组合数还要模P 0.0? ——> Lucas ...
- Gate Of Babylon bzoj 1272
Gate Of Babylon (1s 128MB) babylon [问题描述] [输入格式] [输出格式] [样例输入] 2 1 10 13 3 [样例输出] 12 [样例说明] [数据范围] 题 ...
- 【BZOJ1272】Gate Of Babylon [Lucas][组合数][逆元]
Gate Of Babylon Time Limit: 10 Sec Memory Limit: 162 MB[Submit][Status][Discuss] Description Input ...
- Gate Of Babylon(bzoj 1272)
Description Input Output Sample Input Sample Output 12 HINT /* 容斥+lucas+乘法逆元 首先,看到有限制的只有15个,因此可以用容斥原 ...
- BZOJ 1270: [BeijingWc2008]雷涛的小猫( dp )
简单的dp.. dp(i,j) = max(dp(x,y))+cnt[i][j], (x,y)->(i,j)是合法路径. 设f(i)= max(dp(x,y))(1≤x≤N, 1≤y≤i), g ...
随机推荐
- 《招一个靠谱的移动开发》iOS面试题及详解(上篇)
以下问题主要用于技术的总结与回顾 主要问题总结 单例的写法.在单利中创建数组应该注意些什么. NSString 的时候用copy和strong的区别. 多线程.特别是NSOperation 和 GCD ...
- IOS webview iframe 宽度超出屏幕解决方案
IOS 真机webview中,iframe 却不能很好地适应屏幕大小,总是超出屏幕尺寸,需要左右滚动才能看到完整页面. <div style="overflow: auto;-webk ...
- 2017 国庆湖南 Day6
期望得分:100+100+60=260 实际得分:100+85+0=185 二分最后一条相交线段的位置 #include<cstdio> #include<iostream> ...
- HTML标签小记文本类标签
文本类标签: <input type="text" name="" value="">文本框 type(方式,方法)name文 ...
- v7000数据恢复_MDisk重建数据恢复方法(北亚数据恢复)
很多工程师都有这样的疑问,MDisk重建后还能不能恢复数据呢?应该怎么做才能恢复数据呢?本文这里就以IBM V7000存储为例,详细讲解因为某个MDisk被重建导致的数据丢失的恢复方法.我们本案例中的 ...
- href的理解
您搜索的项目暂未上线,可直接<a style="color: #ff0000;" onclick="onlineTalk();" href="j ...
- 初学深度学习(TensorFlow框架的心得and经验总结)自用环境的总结
初学者的时间大部分浪费在了环境上了: 建议直接上Linux系统,我推荐国产的深度系统,deepin这几年一直在不断的发展,现在15.4已经很不错了 1,图形化界面很漂亮,内置正版crossover,并 ...
- Docker学习笔记 - Docker容器之间的连接
学习目标: 容器之间可以相互连接访问:: --link redis:redisAlias 准备工作 FROM ubuntu:14.04 RUN apt-get install -y ping RUN ...
- python多进程之间的通信:消息队列Queue
python中进程的通信:消息队列. 我们知道进程是互相独立的,各自运行在自己独立的内存空间. 所以进程之间不共享任何变量. 我们要想进程之间互相通信,传送一些东西怎么办? 需要用到消息队列!! 进程 ...
- python多进程--------linux系统中python的os.fork()方法
linux下python 创建子进程的原理: os.fork()方法 的原理 为了实现并发.多任务,我们可以在主程序种开启一个进程或者线程.在类unix操作系统当中(非windows),可以用pyth ...