题链:

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的更多相关文章

  1. bzoj 1272: [BeiJingWc2008]Gate Of Babylon

    Description Solution 如果没有限制,答案就是 \(\sum_{i=0}^{m}C(n+i-1,i)\) 表示枚举每一次取的个数,且不超过 \(m\),方案数为可重组合 发现这个东西 ...

  2. 【BZOJ 1272】 1272: [BeiJingWc2008]Gate Of Babylon (容斥原理+卢卡斯定理)

    1272: [BeiJingWc2008]Gate Of Babylon Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 254  Solved: 12 ...

  3. BZOJ1272: [BeiJingWc2008]Gate Of Babylon

    题解: 多重集合的组合数?还是0-m?有些元素有个数限制? 多重集合的组合数可以插板法,0-m直接利用组合数的公式一遍求出来,个数限制注意到只有15个,那我们就暴力容斥了 AC了真舒畅.. 注意开lo ...

  4. [BeiJingWc2008]Gate Of Babylon

    <基尔伽美修>是人类历史上第一部英雄史诗,两河流域最杰出的文学作品之一.作品讲述了基尔伽美修一生的传奇故事.在动画Fate/staynight中,基尔伽美修与亚瑟王等传说中的英雄人物一起出 ...

  5. 【BZOJ】【1272】【BeiJingWC2008】Gate of Babylon

    组合数学+容斥原理 Orz zyf-zyf 多重集组合数0.0还带个数限制?  ——>  <组合数学>第6章  6.2带重复的组合 组合数还要模P 0.0? ——> Lucas ...

  6. Gate Of Babylon bzoj 1272

    Gate Of Babylon (1s 128MB) babylon [问题描述] [输入格式] [输出格式] [样例输入] 2 1 10 13 3 [样例输出] 12 [样例说明] [数据范围] 题 ...

  7. 【BZOJ1272】Gate Of Babylon [Lucas][组合数][逆元]

    Gate Of Babylon Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description Input ...

  8. Gate Of Babylon(bzoj 1272)

    Description Input Output Sample Input Sample Output 12 HINT /* 容斥+lucas+乘法逆元 首先,看到有限制的只有15个,因此可以用容斥原 ...

  9. 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 ...

随机推荐

  1. *.db-journal 是什么(android sqlite )数据库删除缓存

    sqlite的官方文档,发现该文件是sqlite的一个临时的日志文件,主要用于sqlite数据库的事务回滚操作了.在事务开始时产生,在事务操作完毕时自动删除,当程序发生崩溃或一些意外情况让程序非法结束 ...

  2. 201421123042 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 答: 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户 ...

  3. 洛谷P2894 [USACO08FEB]酒店Hotel

    P2894 [USACO08FEB]酒店Hotel https://www.luogu.org/problem/show?pid=2894 题目描述 The cows are journeying n ...

  4. 遍历JSON

    第一种: each,不做详细说明,太常用了 第二种:我用来遍历单个组,实现前端界面绑定 for(var item in person){ alert("person中"+item+ ...

  5. linux的链接工具secure设置字体大小和颜色

  6. thinkphp调试技巧

    调试的经验:很多时候程序调试不出来,但是又找不出错误,往往是拼写错误可能是很小的拼写错误,很难看出,或者多了一个空格,比如在配置路由的时候'URL_ROUTER_ON '=true,这样设置就会错误, ...

  7. 初学者如何查阅自然语言处理(NLP)领域学术资料

    1. 国际学术组织.学术会议与学术论文 自然语言处理(natural language processing,NLP)在很大程度上与计算语言学(computational linguistics,CL ...

  8. 儿童节,我们从零开始——Python入门资源推荐

    原创 2017-06-01 玄魂工作室 玄魂工作室 今天是六一儿童节,首先祝所有的小朋友身体健康,能永远生活在一个没有战争,没有压迫的世界里,永远快乐. 上一篇文章,很多人都对Python的各种书籍感 ...

  9. Docker Mysql主从同步配置搭建

    Docker Mysql主从同步配置搭建 建立目录 在虚拟机中建立目录,例如路径/home/mysql/master/data,目录结构如下: Linux中 新建文件夹命令:mkdir 文件夹名 返回 ...

  10. java子类重写父类的要点

    子类不能重写父类的静态方法,私有方法.即使你看到子类中存在貌似是重写的父类的静态方法或者私有方法,编译是没有问题的,但那其实是你重新又定义的方法,不是重写.具体有关重写父类方法的规则如下:重写规则之一 ...