刷题——Ant Counting POJ

来源:互联网 发布:jquery.history.js 编辑:程序博客网 时间:2024/06/07 21:12
/*
给四个数:T,A,S,B表示,有A个数,数从1-T,现求集合元素个数为S-B的组合和,只用输出6位
假设给定4个数1,2,3,4每个数只有1个
        0       1       2                   3               4
0       1       0       0                   0               0
1       1       1       0                   0               0
2       1       1,2     12                  0               0
3       1       1,2,3   12,13,23            123             0
4       1       1,2,3,4 12,13,23,14,24,34   123,124,134,234 1234
dp[i][j]表示前i个数组合成j长度的个数
很明显的可以看出,当长度小于等于第i个数的个数时dp[i][j]=dp[i][j-1]+dp[i-1][j]
大于时dp[i][j]=dp[i-1][j]+(dp[i][j-1]-dp[i-1][j-1-t_ni[i]])
大于时有冲突的部分要舍去,画表格和可以看出要舍去的部分时dp[i-1][j-1-t_ni[i]]带来的
dp[i-1][j]为前i-1个数组合成j长度的个数,对于同一个长度,这部分是垂直往下累加的


所以方程为:
dp[i][j]={
        dp[i][j-1]+dp[i-1][j]:t_ni[i]<=j
        dp[i-1][j]+(dp[i][j-1]-dp[i-1][j-1-t_ni[i]]
}


dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1-t_ni[i]]+mod)%mod; 这里去掉冲突的部分会出现负数
我不是很清楚是在什么情况下出现的
*/
#include <stdio.h>
#include <string.h>
int t,a,s,b;
int t_ni[1010];
int dp[1010][100010];
const int mod=1000000;
int main(){
    while(scanf("%d %d %d %d",&t,&a,&s,&b)!=EOF){
        memset(t_ni,0,sizeof(t_ni));
        int x;
        for(int i=0;i<a;i++){
            scanf("%d",&x);
            t_ni[x]++;
        }
        for(int i=0;i<=t;i++){
            dp[i][0]=1;
        }
        for(int i=1;i<=t;i++){
            for(int j=1;j<=b;j++){
                if(j<=t_ni[i]){
                    dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod;
                }
                else{
                    dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1-t_ni[i]]+mod)%mod;
                }
            }
        }
        int num=0;
        for(int i=s;i<=b;i++){
            num=(num+dp[t][i])%mod;
        }
        printf("%d\n",num);
    }
    return 0;
}