/* 将正整数n表示成一系列正整数之和: n = n1 + n2 + ... +nk 其中n1>=n2>=...>=nk>=1,k>=1 正整数的这种表示称为正整数n的划分。求正整数n的不同划分个数 输入: 6 输出: 11 分析:设p(n)表示正整数n的划分树,难以找到递归关系,考虑增加变量 p(n) = q(n,n) 设q(n,m)表示:对于数字n,将最大加数n1不大于m的划分个数 q(n,m)={1,n = m = 1 {q(n,n),n<m,正整数n的划分由n1=n的划分和n1<=n-1的划分组成 {1+q(n,m-1),n=m,包含n只有1个划分,不包含n,划分值比n小 {q(n,m-1) + q(n-m,m),n>m>1,正整数n的最大加数n1不大于m的划分由n1=m的划分和n1<=m-1的划分组成 包含m时,剩余的数为n-m,又因为还有可能包含m,因此是q(n-m,m) 不包含m的划分,划分中所有值比m小,所以是q(n,m-1) */ #include <stdio.h> #include <string.h> const int MAXSIZE = 100; long long g_q[MAXSIZE][MAXSIZE]; long long divideNum(int n,int m) { if(g_q[n][m] != -1) { return g_q[n][m]; } if(n == 1 || m == 1) { return g_q[n][m]= 1; } if(n < m) { return divideNum(n,n); } if(n == m) { return g_q[n][m] = 1 + divideNum(n,m-1); } if(n > m && m > 1) { return g_q[n][m] = divideNum(n,m-1) + divideNum(n-m,m); } } void process() { int n; while(EOF != scanf("%d",&n)) { if(n <= 0) { break; } memset(g_q,-1,sizeof(g_q)); printf("%lld\n",divideNum(n,n)); } } int main(int argc,char* argv[]) { process(); getchar(); return 0; }