这是一道基本的母函数问题,具体什么是母函数和它的作用有多么强大,这在百度百科上说的很明白,我就不多说了,只说说母函数在程序里怎么用。
母函数问题都可以用模板解题的,可重点可能有很多人不理解模板的原理,特别是那三个for循环更是让人晕头转向,我也在网上看了好多讲解,也有我自己的理解,我们就那这个整数拆分的题来说:
首先由这道题我们能写出函数:(#式) (1+x+x^2+x^3+x^4+x^5+....)*(1+x^2+x^4+x^6+x^8+x^10+....)*(1+x^3+x^6+x^9+x^12....).....
在这里说 i ,j,k分别是怎么回事吧。
首先要先用个for循环 把上面#式的第一个括号(1+x+x^2+x^3+x^4+x^5+....)的系数给放在c1中。(c1就是用来存放系数的,c2只是作为中间计算结果的储放,还是要放回到c1中的)
从而再次计算从 # 的 第二个括号开始 , 所以 i 就是代表的# 式第几个括号,
而 用程序模拟手工计算 , 就是 先计算第一个括号 与 第二个括号 计算 , 把结果放到c2中,
在把结果与第三个括号计算 , 把结果放到c2中 , 在和第四个括号计算,........
所以j 就是指的 已经计算出 的 各项的系数 ,比如第一次之后 1+x+x^2+x^3+x^4+x^5+... , j=0指向1 ,
j=1 指向x ,j=2 指向 x^2 .... , 而 k 就是指 将要计算的那个括号中的项 , 因为第i个括号 , 中的指数为0 , i , 2i....所以 k要 + i ;
而结果 c2[j+k] += c1[j]; 就是把 以计算出的 j项的系数 和 现在正在计算的括号的k项相乘 , 所以指数为j+k , 所以结果放到c2[j+k] 中 , 这就是这几个for的作用!(注意:为什么是c2[j+k]+=c1[j],因为目前所计算的第 i 个括号里的每一项的系数都是1,当该项乘以另外一项的时候,系数只取决于另外的一项的系数,而这里的另外一项的系数就是指数为 j 的项的系数,即c[j]。)
本题代码:
#include <stdio.h> #include <string.h> #include <math.h> int main() { int i,j,k,n,c[130],d[130];<span style="white-space:pre"> </span>//注意,题目中的c1和c2在这里分别用c和d代替
while(scanf("%d",&n)!=EOF) { // memset(c,1,sizeof(c)); memset(d,0,sizeof(d)); for(i=0;i<=n;i++) c[i]=1;<span style="white-space:pre"> </span>//这里不用<span style="font-family: 微软雅黑; ">memset(c,1,sizeof(c));</span> for(i=2;i<=n;i++) { for(j=0;j<=n;j++) for(k=0;k+j<=n;k+=i) d[k+j]+=c[j]; memcpy(c,d,sizeof(d)); memset(d,0,sizeof(d)); } printf("%d\n",c[n]); } return 0; }
#include <iostream> using namespace std; const int lmax=10000; //c1是用来存放展开式的系数的,而c2则是用来计算时保存的, //他是用下标来控制每一项的位置,比如 c2[3] 就是 x^3 的系数。 //用c1保存,然后在计算时用c2来保存变化的值。 int c1[lmax+1],c2[lmax+1]; int main() { int n, i, j, k ; // 计算的方法还是模拟手动运算,一个括号一个括号的计算, // 从前往后 while ( cin>>n ) { //对于 1+x+x^2+x^3+ 他们所有的系数都是 1 // 而 c2全部被初始化为0是因为以后要用到 c2[i] += x ; for ( i=0; i<=n; i++ ) { c1[i]=1; c2[i]=0; } //第一层循环是一共有 n 个小括号,而刚才已经算过一个了 //所以是从2 到 n for (i=2; i<=n; i++) { // 第二层循环是把每一个小括号里面的每一项,都要与前一个 //小括号里面的每一项计算。 for ( j=0; j<=n; j++ ) //第三层小括号是要控制每一项里面 X 增加的比例 // 这就是为什么要用 k+= i ; for ( k=0; k+j<=n; k+=i ) { // 合并同类项,他们的系数要加在一起,所以是加法,呵呵。 // 刚开始看的时候就卡在这里了。 c2[ j+k] += c1[ j]; } // 刷新一下数据,继续下一次计算,就是下一个括号里面的每一项。 for ( j=0; j<=n; j++ ) { c1[j] = c2[j] ; c2[j] = 0 ; } } cout<<c1[n]<<endl; } return 0; }