参考仪式黑刃和小飞_Xiaofei大佬们博客;
母函数,又称生成函数,是ACM竞赛中经常使用的一种解题算法,常用来解决组合方面的题目。
本文讲解母函数,但不讲解该算法的基础理论。读者随便找一本组合数学教材便可找到相应的内容,或者直接在网上搜索一下。
母函数通常解决类似如下的问题:
给5张1元,4张2元,3张5元,要得到15元,有多少种组合?
某些时候会规定至少使用3张1元、1张2元、0张5元。
某些时候会规定有无数张1元、2元、5元。
还有比如投两个色子得到6
得到为5.
解题过程
解题时,首先要写出表达式,通常是多项的乘积,每项由多个x^y组成。如(1+x+x^2)(1+x^4+x^8)(x^5+x^10+x^15)。
通用表达式为
n2有时候是无限大。
之后就实现表达式相乘,从第一个因子开始乘,直到最后一个为止。此处通常使用一个循环,循环变量为i。每次迭代的计算结果放在数组a中。计算结束后,a[i]表示权重i的组合数,对应具体问题的组合数。
循环内部是把每个因子的每个项和a中的每个项相乘,加到一个临时的数组b的对应位(这里有两层循环,加上最外层循环,总共有三层循环),之后就把b赋给a。
通用模板
1 | //为计算结果,b为中间结果。 |
P是可能的最大指数。拿钞票组合这题来说,如果要求15元有多少组合,那么P就是15;如果问最小的不能拼出的数值,那么P就是所有钱加起来的和。P有时可以直接省略。具体请看本文后面给出的例题。
如果n2是无穷,那么第二层循环条件j<=n2[i]可以去掉。
优化
1 | //初始化a,因为有last,所以这里无需初始化其他位 |
下面看几个例题。
一、hdu 1085和hdu 1171两题套用了第二个模板,省略了代码中二三层循环里关于last2的条件(其实也可以加上)。
详见:
hdu 1085:http://blog.csdn.net/xiaofei_it/article/details/17041467
hdu 1171:http://blog.csdn.net/xiaofei_it/article/details/17041709
二、hdu 1398套用了第一个模板,因为n2中每一项为无穷大,所以n2数组就省略了。
详见:
hdu 1398:http://blog.csdn.net/xiaofei_it/article/details/17041815
三、hdu 2079、hdu 2082和hdu 2110三题直接套用了第二个模板。
详见:
hdu 2079:http://blog.csdn.net/xiaofei_it/article/details/17042045
hdu 2082:http://blog.csdn.net/xiaofei_it/article/details/17042253
hdu 2110:http://blog.csdn.net/xiaofei_it/article/details/17042421
另外,至于什么时候用第一个模板,什么时候用第二个模板,就看题目规模。
通常情况下,第一个模板就够用了,上面的那些用第二个模板的题目用第一个模板同样能AC。
但如果数据规模比较大(通常不会有这种情况),就要使用第二个模板了。
以上题目n1均为0。
四、hdu 2152是一道n1不为0的题目,我在这里分别套用第一个和第二个模板解题。
详见:
hdu 2152:http://blog.csdn.net/xiaofei_it/article/details/17042497
这些例题都可以在小飞大佬的博客中找到