Description
将一个正整数n表示成一系列正整数的和,如:
N=n1+n2+…+nk (其中n1≥n2≥…≥nk≥1, k≥1)
正整数n的一个这种表示成为正整数n的一个划分。
现在给出一个正整数n(80≥n≥1),求n的不同划分一共有多少种。
Input
输入数据包含多组测试数据,每组测试数据只有一行,仅包含一个正整数n。
Output
对每组输入数据,输出一行,输出n的不同划分的种类数。
Sample Input
1 6
Sample Output
1 11
links:http://jsj.sdibt.edu.cn/JudgeOnline/showproblem?problem_id=1497
算法课本上的对正整数划分的讲解如下:
在正整数n的所有不同的划分中,将最大加数n1不大于m的划分个数记做q(n,m)。可以建立q(n,m)的如下递归关系。
① q(n,m) = 1, n >= 1 当最大加数n1不大于1时,任何正整数n只有一种划分形式,即 n = 1+1+1+~~~+1(n个1)
② q(n,m) = q(n,n) , m >= n 最大加数n1实际上不能大于n。因此, q(1,m) = 1。
③ q(n,n) = 1 + q(n,n-1) 正整数n的划分由n1 = n的划分和n1<=n-1 的划分组成
④ q(n,m) = q(n,m-1) + q(n - m,m) n>m>1 正整数n的最大加数n1不大于m的划分由n1 = m的划分和n1 < = m -1 的划分组成
PS:解释一下④ n1 = m时有: n1 + n -m = n 则此时的划分数目就是对n-m的划分,该划分中最大加数不大于m 即:q(n - m,m)
由以上关系可得
int IntegerDivide(int n,int m) { if(n == 1 || m == 1) return 1; if(n == m) return(1+IntegerDivide(n,n-1)); if(n < m) return IntegerDivide(n,n); if(n < 1 || m < 1) return 0; return IntegerDivide(n,m-1) + IntegerDivide(n-m,m); }
众所周知,递归的效率并不是很高,当测试数据量很大的时候无法AC于是乎必须进行优化
int InDiv(int n,int m) { int j = m,re = 0; while(j >= 1) { if(n == j) { if(ss[n][j] == 0) ss[n][j] == 1; re+=ss[n][j]; j--; continue; } if(n < j) {j = n; continue;} if(n == 1 || m == 1) { if(ss[n][j] == 0) ss[n][j] == 1; re+=ss[n][j]; return re; } if(ss[n][j] == 0) InDiv(n - j,j); re += ss[n][j]; j--; } return re; }
采用循环替代了部分递归,貌似没有优化多少,依旧TL。。。
再次改进:
int ss[81][81]; int IntegerDivide(int n,int m) { if(n == 1 || m == 1) { if(ss[n][m] == 0) ss[n][m] = 1; return ss[n][m]; } if(n == m) { if(ss[n][m] == 0) ss[n][m] = 1+IntegerDivide(n,n-1); return ss[n][m]; } if(n < m) { if(ss[n][m] == 0) ss[n][m] = IntegerDivide(n,n); return ss[n][m]; } if(n < 1 || m < 1) { return 0; } if(ss[n][m] == 0) ss[n][m] = IntegerDivide(n,m-1) + IntegerDivide(n-m,m); return ss[n][m]; }
对于已经计算过的q(n,m)进行存储提高了效率。。。
在网上看到别人写的代码附上挺牛的
#include using namespace std; int i,j,sum[88],s[100][100]; int main(){ s[0][0]=1; for(i=1;i<=80;i++) for(j=1;j<=i;j++) { s[i][j]=s[i-1][j-1]+s[i-j][j]; sum[i]+=s[i][j]; }; while(cin>>i) { cout<
直接从1开始一个递推的计算出1-80所有数的证书划分存入sum。。。时间复杂度O(n^2)