Ant Counting (poj 3046 分组背包)


Language:
Default

Ant Counting

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3142   Accepted: 1246

Description

Bessie was poking around the ant hill one day watching the ants march to and fro while gathering food. She realized that many of the ants were siblings, indistinguishable from one another. She also realized the sometimes only one ant would go for food, sometimes
a few, and sometimes all of them. This made for a large number of different sets of ants!

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.

Input

* Line 1: 4 space-separated integers: T, A, S, and B

* Lines 2..A+1: Each line contains a single integer that is an ant type present in the hive

Output

* Line 1: The number of sets of size S..B (inclusive) 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.

Sample Input

3 5 2 3
1
2
2
1
3

Sample Output

10

Hint

INPUT DETAILS:

Three types of ants (1..3); 5 ants altogether. How many sets of size 2 or size 3 can be made?

OUTPUT DETAILS:

5 sets of ants with two members; 5 more sets of ants with three members

Source

USACO 2005 November Silver

题意:给出T个数字,编号1~T,每个数字有N[i]个。用这些数字组成一个序列,最后问长度在S~B之间的不同序列有多少种。

思路:分组背包。每个蚂蚁家族为一个分组,在每个分组里的选择有N[i]种(选1~N[i])。背包九讲

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

int dp[maxn*100];
int num[maxn];
int t,a,s,b;

int main()
{
    int i,j,x,k;
    while (scanf("%d%d%d%d",&t,&a,&s,&b)!=EOF)
    {
        mem(num,0);
        mem(dp,0);
        FRE(i,1,a)
        {
            sf(x);
            num[x]++;
        }
        dp[0]=1;
        FRE(i,1,t)
        {
            FREE(j,a,0)
            {
                FRE(k,1,num[i])
                {
                    if (j-k>=0)
                    {
                        dp[j]=(dp[j]+dp[j-k])%1000000;
                    }
                }
            }
        }
        int ans=0;
        FRE(i,s,b)
            ans=(ans+dp[i])%1000000;
        pf("%d\n",ans);
    }
    return 0;
}
时间: 2024-08-05 17:51:53

Ant Counting (poj 3046 分组背包)的相关文章

Ant Counting POJ 3046(计数dp)

原题 题目链接 题目分析 计数dp题,感觉其实也可以用组合数学做,但我太菜了,推不出通用公式.dp可以定义dp[i][j]为前i种选j个蚂蚁有多少种选法,然后递推公式如下,其中c[i]表示第i种的数量, dp[i][j]=Σ(min(j,c[i]),k=0)dp[i-1][j-k].可以化简一下,dp[i][j]=∑(c[i],k=0)dp[i-1][j-1-k]+dp[i-1][j]-dp[i-1][j-1-c[i]],最后答案就是dp[t][s]+dp[t][s+1]+...+dp[t][b

poj 3046 Ant Counting 多项式乘法解可重组合数

题意: 裸的求可重组合数. 分析: 多项式乘法求系数的应用啊,不用dp. 代码: //poj 3046 //sep9 #include <iostream> using namespace std; const int maxN=1024; const int maxL=100024; const int mod=1000000; int num[maxN]; int coef[maxL]; int tmp[maxL]; int l1; void mul(int l2) { for(int i

POJ 2486 Apple Tree 树形DP+分组背包

链接:http://poj.org/problem?id=2486 题意:一棵(苹果)树,树上有N个结点(N<=100),起点是结点1.每个结点上有若干个苹果,我可以进行K步操作(K<=200),每次操作是从当前结点移动到相邻的结点,并且到了相邻的结点以后会吃掉上面的所有苹果并且苹果不再长出来,相邻是指两个结点之间有边相连.问在K步操作之后最多可以吃掉多少个苹果. 思路:刚入手的时候觉得是一般的树形背包问题,dp[i][j]代表的是以i为根的子树中走j个结点所能吃到的苹果数,来进行状态转移,但

POJ 2468 Apple Tree 树上瞎搞分组背包

昨晚Debug了好久始终找不出哪里错了,今早再一看发现自己已荣升逗比Beta 2.0 Version. 个人感觉此题为HDU 4003 的弱化版. 把每棵子树都看成一类商品,在每类商品中至多选一件.则问题转化为最基本的分组背包问题. dp[s][c][k] c == 1时,表示在s结点不返回时走K的最大收益,c == 0时,表示在s结点重新返回时走k步的最大收益. 可以dfs从底到顶更新dp.值得一提的是,要保证每个结点的dp[s][c][k]只会被dfs一次,即不能重复更新. 因为重复的dfs

VijosP1250:分组背包

背景 Wind设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了~ 描述 机器人们都想知道谁是最勇敢的,于是它们比赛搬运一些物品. 它们到了一个仓库,里面有n个物品,每个物品都有一个价值Pi和重量Wi,但是有些物品放在一起会爆炸,并且爆炸具有传递性.(a和b会爆炸.b和c会爆炸则a和c会爆炸)机器人们可不想因此损失自己好不容易从Wind那里敲诈来的装备,于是它们想知道在能力范围内,它们最多可以拿多少价值的物品. 你能帮助它们吗? 格式 输入格式 每组测试数据第1行为n,Wmax,

HDU-1011 Starship Troopers (树形DP+分组背包)

题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=105; const

HDU 4003 Find Metal Mineral (树形DP,树形分组背包,经典)

题意:给定一棵树图,n个节点,有边权,要派k<11个机器人从节点s出发,遍历所有的点,每当1只机器人经过1条边时就会花费该边的边权,边是可重复走的.问遍历完所有点的最小花费? 思路: 非常经典,首先需要知道一点,才能往下推理.就是“如果在t点派c个机器人往孩子u,那么最多只有1个机器人能走会回来到t,否则花费总是不划算的”. 稍微证明一下: (1)假设派1个机器人往u,逛一圈回到u的父亲t,花费v= 子树u的边权和*2 + e(t,u)*2.若机器人不要了,那花费肯定比v还要少. (2)假设派2

HDU 1712 ACboy needs your help-dp-(分组背包模型)

题意:n门课程用m天来学习,每门课用不同的天数来学习会有不同的学分,求能得到的最大的学分 分析:第一次接触分组背包.分组背包的模型就是不同的物品有不同的花费和价值,求在规定花费内能得到的最大的价值,这前面跟以前的背包最大的不同是物品分为几组,每组内的物品最多只能选一种:dp[i][j]表示前i组花费j能得到的最大的价值,不过实际在做的时候用一维数组就可以了 公式: for 组i for 花费j (从大到小) for 组内物品k if(j>=c[k]) dp[j]=max(dp[j],dp[j-c

hdu 1712 分组背包

背景:1Y,01背包多加了一个挑选循环而已. 分组背包的典型描述:对于很多背包,把它分为k个组,每个组内的组员是相互冲突的,所以只能选择一个. 我的代码: #include<cstdio> #include<iostream> #include<cstring> using namespace std; int main(void){ int n,m; while(scanf("%d%d",&n,&m),n*n+m*m){ int c