4月22日

poj3046

题意:有n种数a个,求分成s份到b份总共有多少种分法

分析:dp[i+1][j]表示从前i个物品中取出j个共有多少种取法,则前i-1中必然取出的是j-k个,(0<=k<=min(j,vis[i])),所以

dp[i+1][j]=Σdp[i][j-k]=Σdp[i][j-1-k]+dp[i][j]-dp[i][j-1-vis[i]]=dp[i+1][j-1]+dp[i][j]-dp[i][j-1-vis[i]],推到过程详见《调整程序设计》68到69页,注意此处要用滚动数组,不然会爆掉

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 const int maxn=1002;
15 const int mod=1000000;
16 const int maxm=100002;
17 int vis[maxn];
18 int t,a,s,b;
19 int main()
20 {
21     while(cin>>t>>a>>s>>b)
22     {
23         memset(vis,0,sizeof(vis));
24         for(int i=0;i<a;i++)
25         {
26             int x;
27             scanf("%d",&x);
28             vis[x-1]++;
29         }
30         int dp[2][maxm];
31         dp[0][0]=1;
32         dp[1][0]=1;
33         for(int i=0;i<t;i++){
34             for(int j=1;j<=b;j++){
35                 if(j-1-vis[i]>=0)
36                     dp[(i+1)&1][j]=(dp[(i+1)&1][j-1]+dp[i&1][j]-dp[i&1][j-1-vis[i]]+mod)%mod;
37                 else{
38                     dp[(i+1)&1][j]=(dp[(i+1)&1][j-1]+dp[i&1][j])%mod;
39                 }
40             }
41         }
42         long long cnt=0;
43         for(int cas=s;cas<=b;cas++)
44         {
45             cnt=(cnt+dp[t&1][cas])%mod;
46         }
47         cout<<cnt%mod<<endl;
48     }
49     return 0;
50 }
View Code

 

posted @ 2016-04-22 13:00  wolf940509  阅读(130)  评论(0编辑  收藏  举报