题目:http://poj.org/problem?id=3046

多重集合的背包问题。

1.式子:考虑dp[ i ][ j ]能从dp[ i-1 ][ k ](max(0 , j - c[ i ] ) <= k <= j)转移来。

  对于j<=c[ i ],这就是前缀和一样,所以dp[ i ][ j ] = dp[ i ][ j-1 ] + dp[ i-1 ][ j ];

  对于j>c[ i ],加了dp[ i ][ j-1 ] + dp[ i-1 ][ j ]之后会多加了一项dp[ i-1 ][ j-c[ i ]-1 ],减掉即可。

2.意义:dp[ i-1 ][ j ]表示从前面组中选 j 个,dp[ i ][ j-1 ]表示从本组+前面组中选了 j-1 个,再在本组中选1个。

  有一个不合法的情况是dp[ i ][ j-1 ]中已经选了c[ i ]个本组的,就不能再在本组中选1个了。

  而 dp[ i ][ j-1 ]中已经选了c[ i ]个本组的 的方案数就是前面组中选了 j-1-c[ i ] 个的方案数(这样选 j-1 的时候就必须选c[ i ]个本组的了)。减掉即可。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=,M=1e5+,mod=1e6;
int n,m,c[N],l,r,dp[][M],ans;
int main()
{
scanf("%d%d%d%d",&n,&m,&l,&r);int x;
for(int i=;i<=m;i++)
{
scanf("%d",&x);c[x]++;
}
dp[][]=dp[][]=;
for(int i=;i<=n;i++)
{
int u=(i&),v=!u;
for(int j=;j<=r;j++)
{
dp[u][j]=(dp[v][j]+dp[u][j-])%mod;
if(j>c[i])dp[u][j]=((dp[u][j]-dp[v][j-c[i]-])%mod+mod)%mod;
}
}
int u=(n&);
for(int j=l;j<=r;j++)(ans+=dp[u][j])%=mod;
printf("%d",ans);
return ;
}

最新文章

  1. FineReport:任意时刻只允许在一个客户端登陆账号的插件
  2. &lt;&lt;&lt; Java生成Md5
  3. 在Mac mini上编译Android源码
  4. HDU 5651 计算回文串个数问题(有重复的全排列、乘法逆元、费马小定理)
  5. MongoDB学习(一)简介
  6. [LeetCode] 28. Implement strStr() 解题思路
  7. TestNG使用Eclipse建立Test Case - 就是爱Java
  8. Linux 时间同步配置(转)
  9. winform CheckedListBox实现全选/全不选
  10. 用python做中文自然语言预处理
  11. 第二次冲刺spring会议(第六次会议)
  12. 好题 线段树对数据的保存+离线的逆向插入 POJ 2887
  13. Problem A
  14. java笔记----JVM内存
  15. emwin之2D图形绘制问题
  16. javascript常见操作数组的方法
  17. 未能找到类型或命名空间名List
  18. code review &amp; github
  19. bzoj千题计划237:bzoj1492: [NOI2007]货币兑换Cash
  20. java多线程计算和

热门文章

  1. Logback Pattern 日志格式配置
  2. Multiple actions were found that match the request in Web Api
  3. Linux下同时复制多个文件
  4. HTML常用标签——思维导图
  5. secureCRT7.3.4的破解与安装
  6. scala学习手记27 - 下划线与参数
  7. Angularjs注入拦截器实现Loading效果
  8. CSS 技巧总结
  9. ImageView显示图像控件
  10. 【Demo】CSS3 3D转换