poj3046(递推)

来源:互联网 发布:淘宝运营助手找不到 编辑:程序博客网 时间:2024/05/22 10:23

链接:点击打开链接

题意:有A个数,一共T种,从中选一些数作为一个集合,问集合大小在A到B中的种类有多少

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <stdlib.h>using namespace std;const long long MOD=1000000;long long dp[1005][100005];long long num[1005];int main(){    long long T,A,S,B,i,j,x,ans;    while(scanf("%I64d%I64d%I64d%I64d",&T,&A,&S,&B)!=EOF){        memset(num,0,sizeof(num));        for(i=0;i<A;i++){            scanf("%I64d",&x);            num[x-1]++;        }                                               //定义dp[i][j]是从前i种物品中取出j个的组合总数        for(i=0;i<=T;i++)                               //所以可以从前i-1中物品中取出j-k个,再从第i种物        dp[i][0]=1;                                     //品种取出k个,可以推出递推关系式        for(i=0;i<T;i++)                                //dp[i+1][j]=∑{k=0~min(j,a[i])}dp[i][j-k]可以展开        for(j=1;j<=B;j++){                              //因此可以看出∑{k=0~min(j-1,a[i])}dp[i][j-1-k]相比            if(j-1-num[i]>=0)                           //∑{k=0~min(j,a[i])}dp[i][j-k]差了一个dp[i][j]和            dp[i+1][j]=(dp[i+1][j-1]+dp[i][j]-dp[i][j-1-num[i]]+MOD)%MOD;            else                                        //dp[i][j-1-ai],又因为dp[i+1][j]=∑{k=0~min(j,a[i])}            dp[i+1][j]=(dp[i+1][j-1]+dp[i][j])%MOD;     //dp[i][j-k],所以∑{k=0~min(j-1,a[i])}dp[i][j-1-k]=        }                                               //dp[i+1][j-1].所以可以推出优化后的递推式        ans=0;                                          //dp[i+1][j]=dp[i+1][j-1]+dp[i][j]-dp[i][j-1-ai]        for(j=S;j<=B;j++)        ans=(ans+dp[T][j])%MOD;                         //从S到B加和并取余        printf("%I64d\n",ans);    }    return 0;}

0 0
原创粉丝点击