版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88015310
分析:
背包+组合数学
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 310
#define MAXM 10000010
#define MOD 1000000007
using namespace std;
typedef long long ll;
ll dp[2][MAXN*MAXN],sum[2][MAXN*MAXN];
ll fac[MAXM],ifac[MAXM],ans;
ll fsp(ll x,int y){
ll res=1;
while(y){
if(y&1)
res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}
ll C(int n,int m){
// PF("[%d %d]\n",n,m);
return fac[n]*ifac[m]%MOD*ifac[n-m]%MOD;
}
int w[MAXN];
int main(){
// freopen("shopping.in","r",stdin);
// freopen("shopping.out","w",stdout);
int n,m,k;
SF("%d%d%d",&n,&m,&k);
fac[0]=1;
for(int i=1;i<=10000000;i++)
fac[i]=fac[i-1]*i%MOD;
ifac[10000000]=fsp(fac[10000000],MOD-2);
for(int i=10000000;i>=1;i--)
ifac[i-1]=ifac[i]*i%MOD;
for(int i=1;i<=m;i++)
SF("%d",&w[i]);
dp[0][0]=1;
int now=0;
int tot=0;
for(int i=1;i<=m;i++){
now^=1;
dp[now][0]=1;
tot+=w[i];
sum[now^1][0]=1;
for(int j=1;j<=tot;j++){
sum[now^1][j]=(sum[now^1][j-1]+dp[now^1][j])%MOD;
if(j>w[i])
dp[now][j]=(sum[now^1][j]-sum[now^1][j-w[i]-1]+MOD)%MOD;
else
dp[now][j]=sum[now^1][j];
}
}
if(n==m){
if(k>tot)
PF("0");
else
PF("%lld",dp[now][k]);
return 0;
}
for(int i=0;i<=min(k,tot);i++)
ans=(ans+dp[now][i]*C(k-i+n-m-1,n-m-1)%MOD)%MOD;
PF("%lld",ans);
}