hdu_1028_母函数
虽然我很想自己写母函数讲解。。。但是最近事情太多了,就贴个很入门的讲解吧给出一个经典的模板A了这个题
http://blog.csdn.net/vsooda/article/details/7975485
1 //母函数 2 //G(x) = (1 + x^1 + x^2..+x^n)(1 + x^2 + x^4 + x^6 + ...)(1 + x^3 + x^6 +..)(..)(1 + x^n) 3 //第一个表达式(1 + x^1 + x^2..+x^n)中 x的指数代表【解中'1'的出现次数】 比如x^2 = x^(1 * 2) 这是'1'出现了两次 x^3 = x^(1 * 3) '1'出现3次 4 //相似的 第二个表达式(1 + x^2 + x^4 + x^6 + ...) x^4 = x^(2 * 2) '2'出现两次 x^6 = x^(2 * 3) '1'出现3次 5 //...以此类推 【* 1(0次项) 是代表该数字出现次数为0】 6 7 //乘法原理的应用:每一个表达式 表示的都是 某个变量的所有取值【比如第一个表达式 表示'1'可以取的值(即n拆分后'1'出现的次数)可以为 {0,1,2...n}】 8 //每个变量的所有取值的乘积 就是问题的所有的解(在本问题中表现为‘和’) 9 //例子:4 = 2 + 1 + 1就是 x^(1 * 2)【'1'出现2次】 10 // * x^(2 * 1)【'2'出现1次】 11 // * x^(3 * 0)【'3'出现0次】 12 // * x^(4 * 0)【..】 13 // 的结果 14 //上述4个分式乘起来等于 1 * (x^4) 代表 4的一个拆分解 15 //所以 G(x)展开后 其中x^n的系数就是 n的拆分解个数 16 # include <stdio.h> 17 18 int main() 19 { 20 int C1[123], C2[123], n; 21 22 while(scanf("%d", &n) != EOF) 23 { 24 for(int i = 0; i <= n; i++)//初始化 第一个表达式 目前所有指数项的系数都为1 25 { 26 C1[i] = 1; 27 C2[i] = 0; 28 } 29 30 for(int i = 2; i <= n; i++)//第2至第n个表达式 31 { 32 for(int j = 0; j <= n; j++)//C1为前i-1个表达式累乘后各个指数项的系数 33 { 34 for(int k = 0; j + k <= n; k += i)//k为第i个表达式每个项的指数 第一项为1【即x^(i * 0)】(指数k=0),第二项为x^(i * 1)(指数为k=i), 第三项为x^(i * 2)... 所以k的步长为i 35 { 36 C2[j + k] += C1[j];//(ax^j)*(x^k) = ax^(j+k) -> C2[j+k] += a 【第i个表达式每一项的系数都为1; a为C1[j]的值(x^j的系数); C2为乘上第i个表达式后各指数项的系数】 37 } 38 } 39 for(int j = 0; j <= n; j++)//刷新当前累乘结果各指数项的系数 40 { 41 C1[j] = C2[j]; 42 C2[j] = 0; 43 } 44 } 45 printf("%d\n",C1[n]); 46 } 47 48 return 0; 49 }
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N = 123; 5 int c1[N],c2[N]; 6 int main() 7 { 8 int n; 9 while(~scanf("%d",&n)) 10 { 11 for(int i = 0; i <= n; i++) 12 { 13 c1[i] = 1; 14 c2[i] = 0; 15 } 16 for(int i = 2; i <= n; i++){ 17 for(int j = 0; j <= n; j++){ 18 for(int k = 0; j+k <=n; k+=i){ 19 c2[j+k] += c1[j]; 20 } 21 } 22 for(int j = 0; j <= n; j++){ 23 c1[j] = c2[j]; 24 c2[j] = 0; 25 } 26 } 27 printf("%d\n",c1[n]); 28 } 29 return 0; 30 }