题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1028
学习了一下母函数,真是神奇啊!(本文适合了解母函数的朋友阅读,如果不太清楚什么是母函数,请移步Matrix67的文章http://www.matrix67.com/blog/archives/120)
这个题求一个数(n)可以拆分成几种其它不同数的和,我们可以考虑这么个问题:一堆数(<=n)无限取,可以取多少种不同和,进一步分析讨论,这就剥离出母函数的原型了。
首先设系数0为不取,1为取;指数为当前取数的总和。
那么:
单独拿1可以组成:1*x^0+1*x^(1*1)+1*x^(1*2)+... = 1+x^1+x^2+...
单独拿2可以组成:1*x^0+1*x^(2*1)+1*x^(2*2)+... = 1+x^2+x^4+...
单独拿3可以组成:1*x^0+1*x^(3*1)+1*x^(3*2)+... = 1+x^3+x^6+...
那么,他们混合取的话,可以有(1+x^1+x^2+...)*(1+x^2+x^4+...)*(1+x^3+x^6+...)种不同情况。因为我们知道一个数不可能由一个比它大的数与其他非负数组合相加而成的。那么我们可以给定这个取值的范围了。
方便计算起见,我们令x=1,将所有范围内的项进行合并获得解,并将他们的每一项除以1的对应次幂(反正1的任何次幂都是1,这就是为什么取1)就可以得到他们的系数和了。
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 const int maxn = 222; 23 int c1[maxn], c2[maxn]; 24 int n; 25 26 void mother_function() { 27 for(int i = 0; i <= n; i++) { 28 c1[i] = 1; c2[i] = 0; 29 } 30 for(int i = 2; i <= n; i++) { 31 for(int j = 0; j <= n; j++) { 32 for(int k = 0; k + j <= n; k+=i) { 33 c2[j+k] += c1[j]; 34 } 35 } 36 for(int j = 0; j <= n; j++) { 37 c1[j] = c2[j]; 38 c2[j] = 0; 39 } 40 } 41 } 42 43 int main() { 44 while(~scanf("%d", &n)) { 45 mother_function(); 46 printf("%d\n", c1[n]); 47 } 48 return 0; 49 }
母函数好神奇的