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