题链:

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. 【iOS】OC-UTC日期字符串格式化

    NSLog(@"%@",[NSDate date]); NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init ...

  2. php里面的变量的使用

    php里面的变量一般可以直接使用不需要声明,但是这种var_dump($a);就会报错,还有sql语句里面如果某个变量为空也会报错. 如果变量为null,空,未声明都==false,但是不===fal ...

  3. windows安装gcc编译器

    由于vc6.0对c语言编译不是很好,有些语句是正确的,但是编译却不能通过 所以决定在windows中安装gcc编译器来使用! http://www.cnblogs.com/cryinstall/arc ...

  4. 详解JavaScript对象继承方式

    一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使 Parent 构造函数成为 Children 的方法,然 ...

  5. Python内置函数(53)——setattr

    英文文档: setattr(object, name, value) This is the counterpart of getattr(). The arguments are an object ...

  6. guava-19.0和google-collections-1.0 的 ImmutableSet 类冲突

    guava-19.0 google-collections-1.0 都有 ImmutableSet 类,包路径也一致,前者有 copyOf(Collection)? 一.应用报错: 二.解决办法 co ...

  7. PHP环境配置(1)

    Apache下载 Apache下载地址:http://httpd.apache.org/download.cgi 第一步:点击Files for Microsoft Windows 第二步:点击Apa ...

  8. 19届华为实习生笔试之判断iPv6地址类型

    题二: 答案: #coding=utf-8 import re,sys str = sys.stdin.readline().strip() def regex(str): result = &quo ...

  9. python2 当中 遇到 UnicodeDecodeError UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 37: ordinal not in range(128)

    使用python2 总是遇到 UnicodeDecodeErrorUnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in positio ...

  10. POJ-1751 Highways---确定部分边的MST

    题目链接: https://vjudge.net/problem/POJ-1751 题目大意: 有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多 ...