poj 3046 Ant Counting(多重集组合数)
Ant Counting
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 3 Accepted Submission(s) : 2
Being a
bit mathematical, Bessie started wondering. Bessie noted that the hive has T (1
<= T <= 1,000) families of ants which she labeled 1..T (A ants
altogether). Each family had some number Ni (1 <= Ni <= 100) of ants.
How many groups of sizes S, S+1, ..., B (1 <= S <= B <= A) can
be formed?
While observing one group, the set of three ant families was
seen as {1, 1, 2, 2, 3}, though rarely in that order. The possible sets of
marching ants were:
3 sets with 1 ant: {1} {2} {3}
5 sets with 2
ants: {1,1} {1,2} {1,3} {2,2} {2,3}
5 sets with 3 ants: {1,1,2} {1,1,3}
{1,2,2} {1,2,3} {2,2,3}
3 sets with 4 ants: {1,2,2,3} {1,1,2,2} {1,1,2,3}
1 set with 5 ants: {1,1,2,2,3}
Your job is to count the number of
possible sets of ants given the data above.
<br> <br>* Lines 2..A+1: Each line contains a single integer that is
an ant type present in the hive
that can be created. A set like {1,2} is the same as the set {2,1} and should
not be double-counted. Print only the LAST SIX DIGITS of this number, with no
leading zeroes or spaces.
1
2
2
1
3
分析:
多重集组合数也是由多重背包问题拓展出来的一类经典问题。这里仍然给大家讲2种方法:
①朴素方法:
状态:dp[i][j]:前i种中选j个可以组成的种数
决策:第i种选k个,k<=ant[i] && j-k>=0
转移:dp[i][j]=Σdp[i-1][j-k]
复杂度为O(B*Σant[i])即O(B*A)也即O(A^2),虽说这题A最大可到1e5,但是实际数据水,能过
②优化递推式
状态:dp[i][j]:前i种中选j个可以组成的种数
决策:第i种不选或者至少选一个
转移:
1.若不选,显然为dp[i-1][j]
2.若至少选一种,那么为dp[i][j-1]-dp[i-1][j-ant[i]-1]
我们这样来理解,dp[i][j-1] 理解为已经选了第i种一个,至于还选不选这里我们不管它,所以它可以用来代表至少选一个
但是dp[i][j-1]还有一层含义便是前i种中选j-1个可以组成的种数,所以它包含了选ant[i]个第i种,即dp[i-1][j-ant[i]-1],但
dp[i][j] 最多选ant[i]个第i种,所以最后要减去这一种。
所以 dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-ant[i]-1]
复杂度为O(T*B)
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int mod = ;
int dp[][];
int main()
{
int ant[];
int t, a, s, b;
cin >> t >> a >> s >> b;
memset(ant, , sizeof(ant));
int i;
int j;
for (i = ; i <= a; i++)
{
cin >> j;
ant[j]++;
}
for (i = ; i <= t; i++) dp[i][] = ;
dp[][] = dp[][] = ;
for (i = ; i <= t; i++)
{
for (j = ; j <= b; j++)
{
if (j - ant[i] - >= )
{//在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数)
dp[i][j] = (dp[i - ][j] + dp[i ][j - ] - dp[i - ][j - ant[i] - ] + mod) % mod;
}
else
{
dp[i][j] = (dp[i - ][j] + dp[i][j - ])%mod;
}
}
}
int sum = ;
for (i = s; i <= b; i++)
sum = (sum + dp[t][i]) % mod;
cout << sum << endl;
return ;
}
为了节约空间%2;
#include<iostream>
using namespace std;
#define MOD 1000000
int T, A, S, B;
int ant[];
int dp[][];
int ans;
int main()
{
scanf("%d%d%d%d", &T, &A, &S, &B);
for (int i = ; i <= A; i++)
{
int aa;
scanf("%d", &aa);
ant[aa]++;
}
dp[][] = dp[][] = ;
for (int i = ; i <= T; i++)
for (int j = ; j <= B; j++)
if (j - ant[i] - >= ) dp[i % ][j] = (dp[(i - ) % ][j] + dp[i % ][j - ] - dp[(i - ) % ][j - ant[i] - ] + MOD) % MOD; //在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数)
else dp[i % ][j] = (dp[(i - ) % ][j] + dp[i % ][j - ]) % MOD;
for (int i = S; i <= B; i++)
ans = (ans + dp[T % ][i]) % MOD;
printf("%d\n", ans);
return ;
}
poj 3046 Ant Counting(多重集组合数)的更多相关文章
- POJ 3046 Ant Counting ( 多重集组合数 && 经典DP )
题意 : 有 n 种蚂蚁,第 i 种蚂蚁有ai个,一共有 A 个蚂蚁.不同类别的蚂蚁可以相互区分,但同种类别的蚂蚁不能相互区别.从这些蚂蚁中分别取出S,S+1...B个,一共有多少种取法. 分析 : ...
- poj3046 Ant Counting——多重集组合数
题目:http://poj.org/problem?id=3046 就是多重集组合数(分组背包优化): 从式子角度考虑:(干脆看这篇博客) https://blog.csdn.net/viphong/ ...
- poj 3046 Ant Counting
Ant Counting Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4982 Accepted: 1896 Desc ...
- poj 3046 Ant Counting (DP多重背包变形)
题目:http://poj.org/problem?id=3046 思路: dp [i] [j] :=前i种 构成个数为j的方法数. #include <cstdio> #include ...
- poj 3046 Ant Counting——多重集合的背包
题目:http://poj.org/problem?id=3046 多重集合的背包问题. 1.式子:考虑dp[ i ][ j ]能从dp[ i-1 ][ k ](max(0 , j - c[ i ] ...
- POJ 3046 Ant Counting DP
大致题意:给你a个数字,这些数字范围是1到t,每种数字最多100个,求问你这些a个数字进行组合(不包含重复),长度为s到b的集合一共有多少个. 思路:d[i][j]——前i种数字组成长度为j的集合有多 ...
- POJ 3046 Ant Counting(递推,和号优化)
计数类的问题,要求不重复,把每种物品单独考虑. 将和号递推可以把转移优化O(1). f[i = 第i种物品][j = 总数量为j] = 方案数 f[i][j] = sigma{f[i-1][j-k], ...
- 【POJ - 3046】Ant Counting(多重集组合数)
Ant Counting 直接翻译了 Descriptions 贝西有T种蚂蚁共A只,每种蚂蚁有Ni只,同种蚂蚁不能区分,不同种蚂蚁可以区分,记Sum_i为i只蚂蚁构成不同的集合的方案数,问Sum_k ...
- POJ_3046_Ant_Counting_(动态规划,多重集组合数)
描述 http://poj.org/problem?id=3046 n种蚂蚁,第i种有ai个,不同种类的蚂蚁可以相互区分,但同一种类的蚂蚁不能相互区分,从这些蚂蚁中取出s,s+1,s+2,...,b- ...
随机推荐
- 一道sql 关于pivot的面试题
分析:其实它是对时间月份行转列的 表结构设计: 结果: select Name,moth,ISNULL([01],0) as Value1,ISNULL([02],0) as Value2,ISNUL ...
- 1.3 C++引用(Reference)
参考:http://www.weixueyuan.net/view/6328.html 总结: 引用是变量的另外一个别名,不是指针,与原变量名同指相同的内存.可以原变量的值. 在函数中作为形参可以修改 ...
- windows form参数传递过程
三.windows form参数传递过程 在Windows 程序设计中参数的传递,同样也是非常的重要的. 这里主要是通过带有参数的构造函数来实现的, 说明:Form1为主窗体,包含控件:文本框text ...
- iOS 工程自动化 - OCLint
前言 最近一直在做 iOS 工程自动化方向的事情,所以把自己研究和实践的内容进行记录并分享,希望能给大家一些帮助. 为什么要使用 OCLint 做为一个静态代码分析工具,我们引入 OCLint 的目的 ...
- 如何使用 python3 将RGB 图片转换为 灰度图
首先,介绍第一种方法, 使用 PIL 库, PIL库是一种python语言常用的一个图形处理库. 关于 PIL 库的安装本文就不介绍了. from PIL import Image I ...
- google-protobuf安装详解
前言 编译调试项目的过程中涉及到caffe的编译,提示没有安装protobuf的错误,本文详解protobuf的安装: 问题描述 解决步骤 1.查看google protobuf的github,没有直 ...
- ACM 常见词汇
rectangular 美: [rek'tæŋɡjələr] 英: [rek'tæŋɡjʊlə(r)] adj. 矩形的:成直角的 grid 美: [ɡrɪd] 英: [ɡrɪd] n. ...
- CTF-练习平台-Misc之 Telent
三.Telent 下载下来文件,解压压缩包,用记事本打开pcap文件,发现flag
- 【BZOJ1702】[usaco2007margold]队列平衡
原来蛤习线性探测的时候要每次加一个稍大一点的数而不是每次+1……连蛤习都不会写,我tmd是有多弱 原题: N(1<=N<=100000)头牛,一共K(1<=K<=30)种特色, ...
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(十)-- 发布(Windows)
本篇将在这个系列演示的例子上继续记录Asp.Net Core在Windows上发布的过程. Asp.Net Core在Windows上可以采用两种运行方式.一种是自托管运行,另一种是发布到IIS托管运 ...