题目
D
e
v
u
Devu
Devu 想用花去装饰他的花园,他已经购买了
n
n
n个箱子,第
i
i
i个箱子有
f
i
f_i
fi朵花,在同一个的箱子里的所有花是同种颜色的(所以它们没有任何其他特征)。另外,不存在两个箱子中的花是相同颜色的。 现在
D
e
v
u
Devu
Devu 想从这些箱子里选择
s
s
s朵花去装饰他的花园,
D
e
v
u
Devu
Devu 想要知道,总共有多少种方式从这些箱子里取出这么多的花?因为结果有可能会很大,结果需要对
1
0
9
+
7
10^9+7
109+7 取模。
D
e
v
u
Devu
Devu 认为至少有一个箱子中选择的花的数量不同才是两种不同的方案。
输入:
第一行:
n
,
s
n,s
n,s
第二行:
f
1
,
f
2
,
.
.
.
,
f
n
f_1,f_2,...,f_n
f1,f2,...,fn
数据范围:
1
≤
n
≤
20
,
0
≤
s
≤
1
0
14
,
0
≤
f
i
≤
1
0
12
1\le n\le20,0\le s\le10^{14},0\le f_i\le10^{12}
1≤n≤20,0≤s≤1014,0≤fi≤1012
思路
我们考虑对于第
i
i
i 种花的生成函数:
F
i
(
x
)
=
1
+
x
+
x
2
+
.
.
.
+
x
f
i
=
1
−
x
f
i
+
1
1
−
x
F_i(x)=1+x+x^2+...+x^{f_i}=\frac{1-x^{f_i+1}}{1-x}
Fi(x)=1+x+x2+...+xfi=1−x1−xfi+1
那么考虑总方案数的生成函数:
G
(
x
)
=
∏
i
=
1
n
F
i
(
x
)
=
∏
i
=
1
n
1
−
x
f
i
+
1
1
−
x
=
∏
i
=
1
n
(
1
−
x
f
i
+
1
)
(
1
−
x
)
n
G(x)=\prod_{i=1}^nF_i(x)=\prod_{i=1}^n\frac{1-x^{f_i+1}}{1-x}=\frac{\prod_{i=1}^n(1-x^{f_i+1})}{(1-x)^n}
G(x)=i=1∏nFi(x)=i=1∏n1−x1−xfi+1=(1−x)n∏i=1n(1−xfi+1)
然后就套路一波,因为:
H
(
x
)
=
1
+
x
+
x
2
+
.
.
.
=
1
1
−
x
H(x)=1+x+x^2+...=\frac{1}{1-x}
H(x)=1+x+x2+...=1−x1
所以:
G
(
x
)
=
(
∏
i
=
1
n
(
1
−
x
f
i
+
1
)
)
∗
(
1
+
x
+
x
2
+
.
.
.
)
n
G(x)=(\prod_{i=1}^n(1-x^{f_i+1}))*(1+x+x^2+...)^n
G(x)=(i=1∏n(1−xfi+1))∗(1+x+x2+...)n
那我们要求
G
(
x
)
G(x)
G(x) 第
s
s
s 项的系数
a
s
a_s
as
我们发现右边就是不定方程的非负整数解方案数,
g
i
=
C
i
+
n
−
1
n
g_i=C_{i+n-1}^{n}
gi=Ci+n−1n
左边由于
n
n
n 很小,所以考虑二进制枚举
我们记左边枚举所得结果为:
c
x
p
cx^p
cxp那么右边应为
g
s
−
p
g_{s-p}
gs−p
那么
A
n
s
=
∑
S
c
x
p
∗
g
s
−
p
Ans=\sum^Scx^p*g_{s-p}
Ans=∑Scxp∗gs−p
g
i
g_i
gi用
L
u
c
a
s
Lucas
Lucas定理计算即可
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<ctime>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
LL read(){
LL f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return f*x;
}
#define MAXN 20
#define Mod (LL)(1e9+7)
#define INF 0x3f3f3f3f
LL f[MAXN+5];
LL Pow(LL x,LL y){
LL ret=1;
while(y){
if(y&1) ret=ret*x%Mod;
x=x*x%Mod;
y>>=1;
}
return ret;
}
LL Lucas(LL n,LL m){
m=min(m,n-m);
LL ret=1;
while(n&&m){
LL a=1,b=1,n0=n%Mod,m0=m%Mod;
for(LL i=n0;i>=n0-m0+1;i--) a=a*i%Mod;
for(LL i=1;i<=m0;i++) b=b*i%Mod;
ret=ret*a%Mod*Pow(b,Mod-2)%Mod;
n/=Mod,m/=Mod;
}
return ret;
}
int main(){
int n=read();
LL ans=0,s=read();
for(int i=1;i<=n;i++)
f[i]=read();
for(int S=0;S<(1<<n);S++){
LL cnt=s,sign=1;
for(int i=1;i<=n;i++)
if(S&(1<<(i-1)))
cnt-=f[i]+1,sign=-sign;
if(cnt<0) continue;
ans=(ans+sign*Lucas(n+cnt-1,n-1)%Mod)%Mod;
}
printf("%lld\n",(ans+Mod)%Mod);
return 0;
}