poj 3046 Ant Counting

题目大意:
  有编号一到t的蚂蚁家族,每个家族有不同的蚂蚁数。

  问构成S只蚂蚁到构成B只蚂蚁共有多少种方式

  例如

  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}

  

  

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

这道题用母函数来求解。所谓母函数,就是生成函数,说白了就是多项相乘,每一项分别表示每个家族里取一只,两只,三只。。。最后乘出的结果中,x的n次方的系数就表示构成n个蚂蚁有多少种方式代码如下
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #define M 1000000
 5 int cnt[1002] = {0};
 6 int c1[100002] = {0};
 7 int c2[100002] = {0};
 8 int ans[100002] = {0};
 9 int n;
10
11 void multi(int cn1, int cn2) {
12     for(int i = 0; i <= cn1; i++) {
13         for(int j = 0; j <= cn2; j++) {
14             ans[i+j] = (ans[i+j] + c1[i]*c2[j])%M;
15         }
16     }
17     n = cn1 + cn2;
18 }
19
20 int main(int argc, char const *argv[])
21 {
22     //freopen("input.txt","r",stdin);
23     int t, s, a, b;
24     scanf("%d %d %d %d",&t, &a, &s, &b);
25     for(int i = 0; i < a; i++) {
26         int tmp;
27         scanf("%d",&tmp);
28         cnt[tmp]++;
29     }
30     for(int i = 0; i <= cnt[1];i++) {
31         ans[i] = 1;
32     }
33     n = cnt[1];
34     for(int i = 2; i <= t; i++) {
35         memset(c1, 0, sizeof(c1));
36         memset(c2, 0, sizeof(c2));
37         for(int j = 0; j <= n; j++) {
38             c1[j] = ans[j];
39         }
40         for(int j = 0; j <= cnt[i]; j++) {
41             c2[j] = 1;
42         }
43         memset(ans, 0, sizeof(ans));
44         multi(n,cnt[i]);
45     }
46     int ansm = 0;
47     for(int i = s; i <= b; i++) {
48         ansm = (ansm + ans[i])%M;
49     }
50     printf("%d\n",ansm);
51     return 0;
52 }

注意,此题要求输出后六位,要mod M

时间: 2024-07-29 19:07:55

poj 3046 Ant Counting的相关文章

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 3046 Ant Counting(“动态规划” 优化递推关系式)

http://poj.org/problem?id=3046 蚂蚁牙黑,蚂蚁牙红:有A只蚂蚁,来自T个家族.同一个家族的蚂蚁长得一样,但是不同家族的蚂蚁牙齿颜色不同.任取n只蚂蚁(S<=n<=B),求能组成几种集合? 这是<2.3 记录结果再利用的"动态规划" 优化递推关系式>练习题的第二题. 定义 dp[i][j] := 使用前i个家族可以配出来"元素个数为j"的集合的个数. 那么dp[0][0] = 1,不使用任何蚂蚁配出空集的个数为1.

POJ 3046 Ant Counting ( 多重集组合数 &amp;&amp; 经典DP )

题意 : 有 n 种蚂蚁,第 i 种蚂蚁有ai个,一共有 A 个蚂蚁.不同类别的蚂蚁可以相互区分,但同种类别的蚂蚁不能相互区别.从这些蚂蚁中分别取出S,S+1...B个,一共有多少种取法. 分析 :  实际就是要解决 => 从 n 种物品中取出 m 个有多少种取法 ( 同种无法区分 ) 计数问题的 DP 定义必须保证不重复计数 这里定义 dp[i+1][j] => 从前 i 种物品中取出 j 个的组合数 根据定义为了从前 i 种物品中取出 j 个,可以从前 i-1 中取出 j-k 个并从 i

poj 3046 Ant Counting DP

大致题意:给你a个数字,这些数字范围是1到t,每种数字最多100个,求问你这些a个数字进行组合(不包含重复),长度为s到b的集合一共有多少个. 思路:d[i][j]——前i种数字组成长度为j的集合有多少个. 那么,当前考虑第i种数字,我要组成长度为j的集合,只用在前i-1种数字所组成的集合中,只要添加0...cnt[i]个第i种数字之后长度能够达到j的那些集合数加起来 所以方程可以写成d[i][j] = ∑(cnt[i],0)  d[i-1][j-k]. 每种数字最多100个,数字最大为1000

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 man

POJ 2386 Lake Counting 搜索题解

简单的深度搜索就可以了,看见有人说什么使用并查集,那简直是大算法小用了. 因为可以深搜而不用回溯,故此效率就是O(N*M)了. 技巧就是增加一个标志P,每次搜索到池塘,即有W字母,那么就认为搜索到一个池塘了,P值为真. 搜索过的池塘不要重复搜索,故此,每次走过的池塘都改成其他字母,如'@',或者'#',随便一个都可以. 然后8个方向搜索. #include <stdio.h> #include <vector> #include <string.h> #include

bzoj2023[Usaco2005 Nov]Ant Counting 数蚂蚁*&amp;&amp;bzoj1630[Usaco2007 Demo]Ant Counting*

bzoj2023[Usaco2005 Nov]Ant Counting 数蚂蚁&&bzoj1630[Usaco2007 Demo]Ant Counting 题意: t个族群,每个族群有ni只蚂蚁,同族群蚂蚁没有区别.问从所有蚂蚁中选出s到b只蚂蚁有多少方案.t≤1000,ni≤100. 题解: dp,f[i][j]表示考虑第i个族群,剩下j只蚂蚁没选择.则f[i][j]=sum(f[i-1][j-k]),k=0..min(j,n[i]).然而O(n^3)会超时,注意到可以计算f[i-1][

BZOJ2023: [Usaco2005 Nov]Ant Counting 数蚂蚁

2023: [Usaco2005 Nov]Ant Counting 数蚂蚁 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 56  Solved: 16[Submit][Status] Description 有一天,贝茜无聊地坐在蚂蚁洞前看蚂蚁们进进出出地搬运食物.很快贝茜发现有些蚂蚁长得几乎一模一样,于是她认为那些蚂蚁是兄弟,也就是说它们是同一个家族里的成员.她也发现整个蚂蚁群里有时只有一只出来觅食,有时是几只,有时干脆整个蚁群一起出来.这样一来,

POJ 2282 The Counting Problem,组合数学

POJ 2282 The Counting Problem,组合数学 ACM 题目地址:POJ 2282 题意: 给出俩数n,m,求从n~m中0~9分别出现的次数. 分析: 组合数学. 只要能快速算出0~n中各个数的出现次数就能解决问题了. 要把数拆开来看,比如3456=3000+400+50+6. 然后就只要考虑后面都是0的数就行了. 0~3000中,我们要分为两部分来考虑: 在第一位中,0\1\2都出现了1000次. 假设不管第一位,后面那些位数出现0~9的几率是均等的(先不考虑前导0).那