eoj1009
将正整数n表示成一系列正整数之和: n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1(k≥1)
正整数n的这种表示称为正整数n的拆分。求正整数n的不同拆分个数。
例如,正整数6有如下11种不同的拆分:
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
例如,正整数3有如下3种不同的拆分:
3;
2+1;
1+1+1。
对整数n进行拆分,考虑n和当前拆分方法下的最大数m,如在题目例子中:
6被拆分为 4+2,4+1+1,则n=6,m=4
6被拆分为 3+3,3+2+1,3+1+1+1 则n=6,m=3
则得出该题的解法为递归调用f(n,m)
1.当n==1或m==1 只有一种解法
2.当n<m 拆分为正整数之和,所以等同于f(n,n)
3.当n==m 有两种拆分方法,一种为有n,另一种为无n,所以解法为1+f(n,n-1)
4.当n>m 有两种拆分方法,一种含有m,则方法数为剩下n-m个数的拆分方法,另一种不包含m,则为最大数为m-1的拆分方法,所以解法为f(n-m,m)+f(n,n-1)
int in(int n,int m)
{
if(n==1||m==1) return 1;
if(n<=m) return 1+in(n,n-1);
if(n>m) return in(n-m,m)+in(n,m-1);
}
提交后发现超时,于是加入数组,避免重复计算方法数
int in(int n,int m)
{ if(a[n][m]!=0) return a[n][m];//避免重复计算
if(n==1||m==1) { a[n][m]=1;return a[n][m]; }
if(n<=m) { a[n][m]=1+in(n,n-1);return a[n][m]; }
a[n][m]=in(n-m,m)+in(n,m-1);return a[n][m];
}
注意每次拆分一个数需要对数组清零。