码迷,mamicode.com
首页 > 其他好文 > 详细

4月22日

时间:2016-04-22 13:36:01      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:

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

 

4月22日

标签:

原文地址:http://www.cnblogs.com/wolf940509/p/5420885.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!