首页 > 代码库 > 使用母函数方法解答几个问题

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

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

杭电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 void11 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 }
View Code

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 void11 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 }
View Code

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 void11 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 }
View Code

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 void12 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 }
View Code

5. HDU1709 The Balance

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

 

先写到这里。

 

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