使用母函数方法解答几个问题

由于在货币组合的题目中使用了母函数的方法,就顺便搜索一些资料和练习,加深自己的理解。

杭电ACM课件中简要介绍了母函数的方法,并给出了几道相关的题目。

1. HDU1398 Square Coins

使用指定的货币来组合一个给定的目标值,问一共有多少种可能。这道题和我们以前的货币组合题目大同小异,代码如下:

 1 #include <stdio.h>
 2
 3 #define MAXITEMS 2048
 4
 5 int v[17] = {0};
 6 int c1[MAXITEMS];
 7 int c2[MAXITEMS];
 8 int result[MAXITEMS];
 9
10 void
11 MultiplePoly(int c1[], int max1, int c2[], int max2)
12 {
13     int i, j;
14     for (i = 0; i <= max1; i++) {
15         for (j = 0; j <= max2; j++) {
16             result[i + j] += c1[i] * c2[j];
17         }
18     }
19 }
20
21 int
22 main(int argc, char** argv)
23 {
24     int i, j;
25
26     for (i = 0; i < 17; i++) {
27         v[i] = (i+1)*(i+1);
28     }
29
30     memset(c1, 0, sizeof(int) * MAXITEMS);
31     for (i = 0; i <= 300; i++) {
32         c1[i] = 1;
33     }
34
35     for (i = 1; i < 17; i++) {
36         memset(c2, 0, sizeof(int) * MAXITEMS);
37         for (j = 0; j <= 300; j += v[i]) {
38             c2[j] = 1;
39         }
40         memset(result, 0, sizeof(int) * MAXITEMS);
41         MultiplePoly(c1, 300, c2, 300);
42         memmove(c1, result, sizeof(int) * MAXITEMS);
43     }
44     int input;
45     while (scanf("%d", &input) == 1) {
46         if (input == EOF) {
47             break;
48         }
49         printf("%d\n", result[input]);
50     }
51
52     return 0;
53 }

2. HDU1028 Ignatius and the Princess III

将大的数字分解成小的数字,问一共有多少种可能。和货币组合大同小异,代码如下:

 1 #include <stdio.h>
 2
 3 #define MAXITEMS 8196
 4
 5 int v[120] = {0};
 6 int c1[MAXITEMS];
 7 int c2[MAXITEMS];
 8 int result[MAXITEMS];
 9
10 void
11 MultiplePoly(int c1[], int max1, int c2[], int max2)
12 {
13     int i, j;
14     for (i = 0; i <= max1; i++) {
15         for (j = 0; j <= max2; j++) {
16             result[i + j] += c1[i] * c2[j];
17         }
18     }
19 }
20
21 int
22 main(int argc, char** argv)
23 {
24     int i, j;
25
26     for (i = 0; i < 120; i++) {
27         v[i] = i+1;
28     }
29
30     memset(c1, 0, sizeof(int) * MAXITEMS);
31     for (i = 0; i <= 120; i++) {
32         c1[i] = 1;
33     }
34
35     for (i = 1; i < 120; i++) {
36         memset(c2, 0, sizeof(int) * MAXITEMS);
37         for (j = 0; j <= 120; j += v[i]) {
38             c2[j] = 1;
39         }
40         memset(result, 0, sizeof(int) * MAXITEMS);
41         MultiplePoly(c1, 120, c2, 120);
42         memmove(c1, result, sizeof(int) * MAXITEMS);
43     }
44     int input;
45     while (scanf("%d", &input) != EOF) {
46         printf("%d\n", result[input]);
47     }
48
49     return 0;
50 }

3. HDU1085 Holding Bin-Laden Captive

给定个数的1元、2元和5元,问不可能组成的最小的货币值。就是求母函数的第一个系数为0的下标。代码如下:

 1 #include <stdio.h>
 2
 3 #define MAXITEMS 8196
 4
 5 int v[3] = {1, 2, 5};
 6 int c1[MAXITEMS];
 7 int c2[MAXITEMS];
 8 int result[MAXITEMS];
 9
10 void
11 MultiplePoly(int c1[], int max1, int c2[], int max2)
12 {
13     int i, j;
14     int *pResult;
15     for (i = 0; i <= max1; i++) {
16         if (c1[i] != 0) {
17             pResult = &result[0];
18             pResult += i;
19             for (j = 0; j <= max2; j++) {
20                 pResult[j] += c1[i] * c2[j];
21             }
22         }
23     }
24 }
25
26 int
27 main(int argc, char** argv)
28 {
29     int i, j;
30     int resultIdx;
31     int num[3] = {0, 0, 0};
32     while (scanf("%d %d %d", &num[0], &num[1], &num[2]) == 3) {
33         if (num[0] == 0 && num[1] == 0 && num[2] == 0) {
34             break;
35         }
36         memset(c1, 0, sizeof(int) * MAXITEMS);
37         for (i = 0; i <= num[0]; i++) {
38             c1[i] = 1;
39         }
40         for (i = 1; i < 3; i++) {
41             memset(c2, 0, sizeof(int) * MAXITEMS);
42             for (j = 0; num[i] >= 0; j += v[i], num[i]--) {
43                 c2[j] = 1;
44             }
45             memset(result, 0, sizeof(int) * MAXITEMS);
46             MultiplePoly(c1, 3000, c2, 5000);
47             memmove(c1, result, sizeof(int) * MAXITEMS);
48         }
49         for (resultIdx = 0; resultIdx < MAXITEMS; resultIdx++) {
50             if (result[resultIdx] == 0) {
51                 printf("%d\n", resultIdx);
52                 break;
53             }
54         }
55     }
56
57     return 0;
58 }

4. HDU1171 Big Event in HDU

有若干件物品,每种物品有它的价值。现在要将这些物品分配给两个机构A和B,要求分给A的不少于分给B的。等价于求母函数的系数不为零的项的中间一个项,就是给A分配的物品总价值,余下的就是给B的。代码如下(不能AC,报超时,暂时不管):

 1 #include <stdio.h>
 2
 3 #define MAXITEMS 250000
 4
 5 int v[50];
 6 int m[50];
 7 int c1[MAXITEMS];
 8 int c2[MAXITEMS];
 9 int result[MAXITEMS];
10
11 void
12 MultiplePoly(int c1[], int max1, int c2[], int max2)
13 {
14     int i, j;
15     int *pResult;
16     for (i = 0; i <= max1; i++) {
17         if (c1[i] != 0) {
18             pResult = &result[0];
19             pResult += i;
20             for (j = 0; j <= max2; j++) {
21                 pResult[j] += c1[i] * c2[j];
22             }
23         }
24     }
25 }
26
27 int
28 main(int argc, char** argv)
29 {
30     int i, j, k;
31     int inputCnt;
32     int sum;
33     int tmp;
34     while (scanf("%d", &inputCnt) == 1)
35     {
36         if (inputCnt < 0) {
37             break;
38         }
39         memset(v, 0, sizeof(int) * 50);
40         memset(m, 0, sizeof(int) * 50);
41         /* read the v array and m array */
42         for (k = 0; k < inputCnt; k++) {
43             scanf("%d %d", &v[k], &m[k]);
44         }
45         /*printf("sum: %d\n", sum);*/
46         sum = 0;
47         /* initial first polynomial */
48         memset(c1, 0, sizeof(int) * MAXITEMS);
49         tmp = m[0];
50         sum += m[0]*v[0];
51         for (i = 0; tmp >= 0; i+=v[0], tmp--) {
52                 c1[i] = 1;
53         }
54         /* then initial others, if there is any */
55         for (i = 1; i < inputCnt; i++) {
56             memset(c2, 0, sizeof(int) * MAXITEMS);
57             tmp = m[i];
58             sum += m[i]*v[i];
59             for (j = 0; tmp >= 0; j += v[i], tmp--) {
60                 c2[j] = 1;
61             }
62             memset(result, 0, sizeof(int) * MAXITEMS);
63             MultiplePoly(c1, sum, c2, m[i]*v[i]);
64             memmove(c1, result, sizeof(int) * MAXITEMS);
65         }
66         /* output */
67         memset(result, 0, sizeof(int) * MAXITEMS);
68         int count = 0;
69         for (i = 0; i <= sum; i++) {
70             if (c1[i] > 0) {
71                 result[count] = i;
72                 count++;
73             }
74         }
75         int partA = result[count/2];
76         int partB = sum - partA;
77         printf("%d %d\n", partA, partB);
78     }
79     return 0;
80 }

5. HDU1709 The Balance

有一架天平,给你若干个砝码,可以把砝码放在左边或者右边,能够表示出不同的克数。砝码放在左边,表示在母函数中系数为负,右边则为正。代码还没写。

先写到这里。

时间: 2024-10-14 10:43:08

使用母函数方法解答几个问题的相关文章

母函数入门+模板(转)

在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型. 这里先给出两句话,不懂的可以等看完这篇文章再回过头来看: 1.“把组合问题的加法法则和幂级数

转 母函数

在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型. 母函数的作用: 1."把组合问题的加法法则和幂级数的乘幂对应起来" 2."

【组合数学】 05 - 经典计数方法

1. 基本计数的母函数 现在来用母函数来求解基本计数问题,母函数既可以完成自动计数,还能表示计数本身,像Stirling数这种就只能用母函数表示.自动计数适用于可以分步的计数问题,并且目标值是每步值之和,这与多项式的运算性质有关. 1.1 组合数和分划数 直观上最符合这一特点的就是模型2,从\(n\)个可区别对象中选出\(m个\).限制第\(k\)个对象被取的次数在集合\(M_k\)中,它被选情况的母函数是\(\sum\limits_{i\in M_k}x^i\),所有元素被选择的情况可以借助母

母函数详解

母函数(Generating function)详解 在数学中,某个序列的母函数是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型. 这里先给出两句话,不懂的可以等看完这篇文章再回过头来看: "把组合问题的加法法则和幂级数的t的

HDU 1085 Holding Bin-Laden Captive!(母函数,或者找规律)

Holding Bin-Laden Captive! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 17653    Accepted Submission(s): 7902 Problem Description We all know that Bin-Laden is a notorious terrorist, and he h

精讲母函数

在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型. 这里先给出两句话,不懂的可以等看完这篇文章再回过头来看: 1.“把组合问题的加法法则和幂级数

母函数的应用

参考文献 在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型. 这里先给出两句话,不懂的可以等看完这篇文章再回过头来看: 1."把组合问题的加法法

母函数 入门 + 模板

转自:母函数 入门 + 模板  感谢 在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型. 这里先给出两句话,不懂的可以等看完这篇文章再回过头来看

[转] 母函数详解

转载自:http://blog.csdn.net/lishuhuakai/article/details/8044431 母函数(Generating function)详解 在数学中,某个序列的母函数是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的方法称为母函数方法. 母函数可分为很多种,包括普通母函数.指数母函数.L级数.贝尔级数和狄利克雷级数.对每个序列都可以写出以上每个类型的一个母函数.构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序