●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 ...
随机推荐
- Flask 蓝图(Blueprint)
蓝图使用起来就像应用当中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝图之间互相不影响.但是它们又属于应用中,可以共享应用的配置.对于大型应用来说,我们可以通过添加蓝图来扩 ...
- ubuntu1604使用源码方式安装ruby2.5.0
本文介绍ubutntu1604环境下源代码方式安装ruby 版本2.5.0 如果内存小于2G可以开启虚拟内存,下面的命令开启4G虚拟内存 sudo dd if=/dev/zero of=/swap b ...
- 根据抽象工厂实现的DBHelpers类
public abstract class DBHelper { public static SqlConnection conn = new SqlConnection("server=l ...
- Golang学习--平滑重启
在上一篇博客介绍TOML配置的时候,讲到了通过信号通知重载配置.我们在这一篇中介绍下如何的平滑重启server. 与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只 ...
- leetcode题解 6.ZigZag Conversion
6.ZigZag Conversion 题目: The string "PAYPALISHIRING" is written in a zigzag pattern on a gi ...
- PHP常见排序算法
$a = [1, 3, 5, 2, 4, 6, 12, 60, 45, 10, 32];$len = count($a);$num=0;/* * 冒泡排序 * 原理:不停的对相邻两个数进行比较,直到最 ...
- BizTalk 2016 配置 RosettaNet遇到的坑
本文只针对已经安装好BizTalk 2016 需要在安装RosettaNet加速器的伙伴. IIS配置 权限问题 错误信息 Failed to get IIS metabase property. E ...
- 用Vue.js开发微信小程序:开源框架mpvue解析
前言 mpvue 是一款使用 Vue.js 开发微信小程序的前端框架.使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为 H5 和小程序提供了代码复用的能力.如果想将 H5 项目改造为小程 ...
- dubbo的InvocationChain
个人觉得dubbo比较好的设计是:一个是Cooma微容器设计.另一个就是InvocationChain了 Cooma微容器是自己实现了一套SPI,方便了用户做扩展: InvocationChain类似 ...
- Docker学习笔记 - Docker的镜像
一个容器实际上是运行在宿主机上的一个进程. 只不过在启动这个进程之前进行了一些特殊处理,让这个容器进入了一个全新的虚拟环境,与宿主机的环境分开, 所以这个进程及其子进程认为自己运行在一个独立的世界里面 ...