dp[i][j]表示前i种蚂蚁组成元素个数为j的集合有多少种。
则dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + ... + dp[i-1][ max(0,j-a[i])];
直接算的话复杂度为O(TA^2)
状态的转移是一个区间内的数的和,所以再用一个数组f[i][j]记录dp[i][j]的前缀和。
dp[i][j] = f[i-1][j]-f[i-1][j-a[i]-1];
复杂度为O(TA)
同时可以用滚动数组优化空间复杂度。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> using namespace std;
const int maxn = ;
const int mod = ;
int dp[maxn];
int da[];
int f[maxn];
int n,A,a,b;
int main()
{
while( scanf("%d%d%d%d", &n, &A, &a, &b) != EOF)
{
memset(da,,sizeof(da));
for(int i = ;i <= A; i++)
{
int x; scanf("%d", &x);
da[x]++;
}
dp[]=;
f[]=;
int maxv=;
for(int i = ; i <= n; i++)
{
maxv += da[i];
for(int i=;i<=maxv;i++)
f[i]=(f[i-]+dp[i])%mod;
for(int j=; j <= min(b,maxv); j++)
{
dp[j]=(f[j]-(j-da[i]<=?:f[j-da[i]-]))%mod;
}
}
int res=;
for(int i=a;i<=b;i++)
res=(res+dp[i])%mod;
printf("%d\n",res);
}
return ;
}