题意 : 有 n 种蚂蚁,第 i 种蚂蚁有ai个,一共有 A 个蚂蚁。不同类别的蚂蚁可以相互区分,但同种类别的蚂蚁不能相互区别。从这些蚂蚁中分别取出S,S+1...B个,一共有多少种取法。

分析 : 

实际就是要解决 => 从 n 种物品中取出 m 个有多少种取法 ( 同种无法区分 )

计数问题的 DP 定义必须保证不重复计数

这里定义 dp[i+1][j] => 从前 i 种物品中取出 j 个的组合数

根据定义为了从前 i 种物品中取出 j 个,可以从前 i-1 中取出 j-k 个并从 i 种中取出 k 个

即 dp[i+1][j] = ∑dp[i][j-k] 【 0 ≤ k ≤ min(j, ant[i]) 】

但是这个递推式的求和太耗时间,实际可以优化,考虑两种情况 j ≤ ant[i] 和 j > ant[i]

① j ≤ ant[i] ( 即 j-1 < ant[i] )

此时 ∑ 的上界 min( j, ant[i] ) = j ,将式子展开有 dp[i][0]+dp[i][1]+dp[i][2]...dp[i][j] ( k 从大到小枚举 )

将展开式的 dp[i][j] 取出来那么将得到 ∑dp[i][j-1-k] 【 0 ≤ k ≤ j-1 】( 其实这个就是 dp[i+1][j-1] !!! )

那么最后 dp[i+1][j] = dp[i+1][j-1] + dp[i][j]

② j > ant[i]

此时 ∑ 的上界 min( j, ant[i] ) = ant[i],将式子展开有 dp[i][j-ant[i]]+dp[i][j-ant[i]+1]...dp[i][j]

对比 ① 的结果,很明显如果用 ① 的结果 - dp[i][j-ant[i]-1] 就能得到上面的展开式了!

所以 ② 的情况下,dp[i+1][j] = ( dp[i+1][j-1] + dp[i][j] ) - dp[i][j-ant[i]-1]

#include<stdio.h>
#include<string.h>
using namespace std;
const int mod = 1000000;
int dp[1010][100010];
int num[1010];
int main(void)
{int T, A, S, B;while(~scanf("%d %d %d %d", &T, &A, &S, &B)){memset(num, 0, sizeof(num));for(int temp,i=1; i<=A; i++)scanf("%d", &temp),num[temp-1]++;for(int i=0; i<=T; i++)dp[i][0] = 1;for(int i=0; i<T; i++){for(int j=1; j<=B; j++){if(j - 1 - num[i] >= 0)dp[i+1][j] = (dp[i+1][j-1] + dp[i][j] - dp[i][j-1-num[i]] + mod)%mod;elsedp[i+1][j] = (dp[i+1][j-1] + dp[i][j])%mod;}}int ans = 0;for(int i=S; i<=B; i++)ans = (ans + dp[T][i])%mod;printf("%d\n", ans);}return 0;
}

View Code

其实 DP 的阶段 ( 数组第一维 ) 只跟前一个有关系,故用滚动数组优化

#include<stdio.h>
#include<string.h>
using namespace std;
const int mod = 1000000;
int dp[2][100010];
int num[1010];
int main(void)
{int T, A, S, B;while(~scanf("%d %d %d %d", &T, &A, &S, &B)){memset(num, 0, sizeof(num));for(int temp,i=1; i<=A; i++)scanf("%d", &temp),num[temp-1]++;int idx = 0;dp[idx][0] = dp[idx^1][0] = 1;for(int i=0; i<T; i++,idx^=1){for(int j=1; j<=B; j++){if(j - 1 - num[i] >= 0)dp[idx^1][j] = (dp[idx^1][j-1] + dp[idx][j] - dp[idx][j-1-num[i]] + mod)%mod;elsedp[idx^1][j] = (dp[idx^1][j-1] + dp[idx][j])%mod;}}int ans = 0;for(int i=S; i<=B; i++)ans = (ans + dp[idx][i])%mod;printf("%d\n", ans);}return 0;
}

View Code

转载于:https://www.cnblogs.com/LiHior/p/8143884.html

POJ 3046 Ant Counting ( 多重集组合数 经典DP )相关推荐

  1. Ant Counting多重集组合数

    Ant Counting 题目描述: 有一天,贝茜无聊地坐在蚂蚁洞前看蚂蚁们进进出出地搬运食物.很快贝茜发现有些蚂蚁长得几乎一模一样,于是她认为那些蚂蚁是兄弟,也就是说它们是同一个家族里的成员.她也发 ...

  2. POJ 3046 Ant Counting

    题目链接 题意 一共有T种蚂蚁编号从1 到 T,给出A个蚂蚁序列,问任取n个蚂蚁一共可以组几种集合,求S到B的种类和 AC dp 状态转移方程为: K表示当前蚂蚁的数目 #include <io ...

  3. POJ 3046 Ant Counting(递推,和号优化)

    计数类的问题,要求不重复,把每种物品单独考虑. 将和号递推可以把转移优化O(1). f[i = 第i种物品][j = 总数量为j] = 方案数 f[i][j] = sigma{f[i-1][j-k], ...

  4. bzoj 1630 2023: [Usaco2005 Nov]Ant Counting 数蚂蚁(有重复元素的组合数)

    2023: [Usaco2005 Nov]Ant Counting 数蚂蚁 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 281  Solved: 18 ...

  5. 多重集表示合json数据_计数DP(划分数,多重集组合数)

    划分数:把n个无区别的物品划分成不超过m组. dp[i][j]=j的i划分的总数. dp[i[j]=dp[i][j-i]+dp[i-1][j] 即:将j个物品分成i份,有两种情况:每份划分都大于等于1 ...

  6. 经典dp最长递增子序列

    经典dp最大递增子序列,  看了好长时间,看了好多版本.最终因为这个看懂,也觉得这个是最全面的吧,我感觉我好菜啊. http://wenku.baidu.com/view/bed07b15552707 ...

  7. 【组合数学】排列组合 ( 多重集组合数示例 | 三个计数模型 | 选取问题 | 多重集组合问题 | 不定方程非负整数解问题 )

    文章目录 一.多重集组合示例 二.三个计数模型 排列组合参考博客 : [组合数学]基本计数原则 ( 加法原则 | 乘法原则 ) [组合数学]集合的排列组合问题示例 ( 排列 | 组合 | 圆排列 | ...

  8. poj 3728 The merchant// lca(倍增实现) + dp || tarjan+并查集路径上dp

    poj 3728 The merchant// lca(倍增实现) + dp Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: ...

  9. poj 2386 Lake Counting

    poj   2386   Lake Counting                           题目链接:http://poj.org/problem?id=2386 题目大意:数湖. 题目 ...

最新文章

  1. 【转】android的startActivityForResult学习心得
  2. OpenShift 之 Image Registry、Image 和 ImageStream 概念和相关操作
  3. 黑马lavarel教程---10、lavarel模型关联
  4. Django(part17)--form表单提交数据
  5. c语言中指,浅析C语言中指与数组.doc
  6. SharePoint 2010 master page 控件介绍(5):其他
  7. C语言 fwirte 函数 - C语言零基础入门教程
  8. 什么叫显示动力学_通过流体动力学研究找到制作煎饼的最佳方法
  9. 2.nginx 配置
  10. 自动驾驶_感知_分割_车道线检测
  11. SuperMap iClient3D for WebGL 示范案例(一)倾斜模型加载
  12. SharePoint2010探索日志
  13. python连接阿里云服务器_阿里云服务器python
  14. 浅谈Linux管线命令grep
  15. 论文图片绘制 Python绘制多分类混淆矩阵及可视化(颜色随正确率渐变)
  16. WPF图片背景色过滤
  17. 中文转换为日文的几点注意事项
  18. 腾讯云 直播 OBS 在线推流
  19. 管你 JDK 还是 Linux,我 Netty 稳坐钓鱼台
  20. TortoiseGit GitLab使用教程

热门文章

  1. c语言快速排序_Damp;C思想-快速排序算法
  2. 计算机小白学生物信息的难度,基因表达数据分析,对于还是分子生物学小白的我来说太难了。。。...
  3. java设计app_一个APP的诞生——从零开始设计你的手机应用
  4. java全局变量和局部变量_Java 10:局部变量类型推断
  5. aws rds恢复数据库_Amazon RDS – AWS关系数据库服务
  6. Python字符串endswith()
  7. 了解SQL INSERT INTO SELECT语句
  8. 如何在Windows 10上安装Python
  9. Akka定义Actors和消息《two》译
  10. spire.pdf系列文章