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)
同时可以用滚动数组优化空间复杂度。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn = 110005; const int mod = 1000000; int dp[maxn]; int da[1005]; int f[maxn]; int n,A,a,b; int main() { while( scanf("%d%d%d%d", &n, &A, &a, &b) != EOF) { memset(da,0,sizeof(da)); for(int i = 1;i <= A; i++) { int x; scanf("%d", &x); da[x]++; } dp[0]=1; f[0]=1; int maxv=0; for(int i = 1; i <= n; i++) { maxv += da[i]; for(int i=0;i<=maxv;i++) f[i]=(f[i-1]+dp[i])%mod; for(int j=1; j <= min(b,maxv); j++) { dp[j]=(f[j]-(j-da[i]<=0?0:f[j-da[i]-1]))%mod; } } int res=0; for(int i=a;i<=b;i++) res=(res+dp[i])%mod; printf("%d ",res); } return 0; }