在 Byteland一共开着 n家商店,编号依次为 1到 n,其中编号为1到 m的商店有日消费量上限,第 i家商店的日消
费量上限为wi。Byteasar每次购物的过程是这样的:依次经过每家商店,然后购买非负整数价格的商品,并在结账
的时候在账本上写上在这家商店消费了多少钱。当然,他在这家商店也可以什么都不买,然后在账本上写上一个0
。这一天, Byteasar日常完成了一次购物,但是他不慎遗失了他的账本。他只记得自己这一天一共消费了多少钱
,请写一个程序,帮助 Byteasar计算有多少种可能的账单。
第一行包含三个正整数
n, m, k,分别表示商店的个数、有限制的商店个数以及总消费量。
第二行包含 m个整数,依次表示 w1;w2...wm。
1 ≤ m ≤ n,0≤ wi ≤ 300,1 ≤ n, k ≤ 5000000
m<=300
输出一行一个整数,即可能的账单数,由于答案可能很大,请对1000000007取模输出。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int ha=1000000007;
const int maxn=10000000;
int jc[maxn+5],ni[maxn+5];
int f[2][100005],n,m,K,tot;
int ans=0,a[305],now,pre;
inline int add(int x,int y){
x+=y;
return x>=ha?x-ha:x;
}
inline int ksm(int x,int y){
int an=1;
for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
return an;
}
inline void init(){
jc[0]=1;
for(int i=1;i<=maxn;i++) jc[i]=jc[i-1]*(ll)i%ha;
ni[maxn]=ksm(jc[maxn],ha-2);
for(int i=maxn;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
}
inline int C(int x,int y){
if(x<y) return 0;
return jc[x]*(ll)ni[y]%ha*(ll)ni[x-y]%ha;
}
inline void dp(){
f[0][0]=1;
for(int i=1;i<=m;i++){
tot+=a[i];
pre=now,now^=1;
for(int j=0,sum=0;j<=tot;j++){
sum=add(sum,f[pre][j]);
if(j>a[i]) sum=add(sum,ha-f[pre][j-a[i]-1]);
f[now][j]=sum;
}
}
}
inline void calc(){
if(!n){
if(K<=tot) ans=f[now][K];
else ans=0;
}
else for(int i=min(K,tot);i>=0;i--) ans=add(ans,f[now][i]*(ll)C(K-i+n-1,K-i)%ha);
}
int main(){
init();
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=m;i++) scanf("%d",a+i);
n-=m;
dp();
calc();
printf("%d\n",ans);
return 0;
}