题目大意:给你$n$个箱子,每个箱子里有$a_{i}$个花,你最多取$s$个花,求所有取花的方案,$n<=20$,$s<=1e14$,$a_{i}<=1e12$

容斥入门题目

把取花想象成往箱子里放花,不能超过箱子上限

$n$很小,考虑状压

如果去掉$a_{i}$的限制,我们取物品的方案数是$C_{s+n-1}^{n-1}$,可以想象成$s+n-1$个小球,我们取出$n-1$个隔板,分隔出来的其他$n$个部分就是每个箱子里花的数量

但这样会算入不合法的方案,我们需要再去掉不合法的方案

假设我们要满足i合法,那么首先分配给$i$,$ai+1$朵花,来保证它是不合法的

然后,剩余$s+n-(ai+1)-1$朵花,我们仍然要分配给$n$个箱子,取出$n-1$个隔板,总方案数减去$C_{s+n-(ai+1)-1}^{n-1}$

然而我们由算入了一些情况,即$i$不合法,$j$也不合法$(j!=i)$,在计算$i$和计算$j$时都去掉了这种情况,我们还要把它加回来

总方案再加回来$C_{s+n-(ai+aj+2)-1}^{n-1}$

然后又多减掉了$i,j,k$都不合法....依次容斥即可

公式太长,也不好理解就不列了

这道题的组合数很大,不能直接求,我们需要一些优化

因为$n$很小,但$s$很大,所以上下化简掉阶乘里那一段特别长的部分,剩下的$O(n)$暴力计算就行了

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N 150
#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define mod 1000000007
using namespace std;
//re
/*int gint()
{
int ret=0,fh=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
return ret*fh;
}*/
int n;
ll sum,ma;
ll a[N],mu[N],inv[N],minv[N];
ll qpow(ll x,ll y){
ll ans=;
if(y){
if(y&) ans=ans*x%mod;
x=x*x%mod,y>>=;
}return ans;
}
void Pre(){
minv[]=minv[]=inv[]=inv[]=;
for(int i=;i<=n;i++)
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod,minv[i]=minv[i-]*inv[i]%mod;
}
ll C(ll a,ll b)
{
ll ans=;
if(b>a) return ;
if(b==) return ;
for(ll j=a-b+;j<=a;j++)
ans=j%mod*ans%mod;
ans=ans*minv[b]%mod;
return ans;
}
ll Lucas(ll a,ll b)
{
if(b>a) return ;
if(a<mod&&b<mod) return C(a,b);
else return Lucas(a%mod,b%mod)*Lucas(a/mod,b/mod)%mod;
} int main()
{
//freopen("t1.in","r",stdin);
scanf("%d%I64d",&n,&ma);
int tot=(<<n)-;
for(int i=;i<n;i++)
scanf("%I64d",&a[i]);
ll ans=;
Pre();
for(int s=;s<=tot;s++)
{
ll res=ma;int cnt=;
for(int i=;i<n;i++)
if(s&(<<i)) res-=a[i]+,cnt++;
if(res<) continue;
(ans+=1ll*(cnt&?-:)*Lucas(res+n-,n-)%mod+mod)%=mod;
}
printf("%I64d\n",ans);
return ;
}

最新文章

  1. bootstrap 笔记
  2. JavaWeb学习笔记——Ajax
  3. [Angularjs]视图和路由(二)
  4. [转]Android-网络通信框架Volley使用详解
  5. C++----练习--bool类型作为特别的int要区别对待
  6. 异步方式向WPF ListBox控件中一条一条添加记录
  7. [LeetCode][Python]Median of Two Sorted Arrays
  8. poj2676解题报告
  9. Liunx上传下载和压缩问题分享
  10. Atom的追踪函数插件和自定义语法
  11. 如何利用panel在一个窗口中实现诸多页面的显示
  12. 利用 jQuery 来验证密码两次输入是否相同
  13. LeetCode题解之Merge k Sorted Lists 解法二
  14. Linux操作系统中文件结构stat中st_size的说明以及对于文件中洞(Holes)的理解
  15. struts2 OGNL(Object-Graph Navigation Language) 井号,星号,百分号
  16. 带分数dfs+剪枝优化
  17. Mysql 漏洞利用(越权读取文件,实战怎么从低权限拿到root密码)[转]
  18. php 查看使用多少内存
  19. 关于SpringCloud微服务架构概念的一点理解
  20. IP和java.net.InetAddress类的使用

热门文章

  1. 设置mySql的编码方式为utf-8
  2. luogo p3379 【模板】最近公共祖先(LCA)
  3. bindActionCreators作用
  4. MHA 主从切换过程及日志分析
  5. 2019-03-21 Python Request InsecureRequestWarning
  6. Java基础学习总结(57)——Jrebel插件热部署
  7. UVA 12507 Kingdoms
  8. Ubuntu 常用快捷键
  9. HDU——T 1498 50 years, 50 colors
  10. Could not connect to SMTP host: localhost, port: 25;