夏夜、

心若平似镜、何题不AC。

POJ Ant Counting DP

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 = 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\n",res);
    }
    return 0;
}
View Code

 

posted on 2014-04-22 16:01  BMan、  阅读(246)  评论(0编辑  收藏  举报

导航