整数划分,是指把一个正整数n表示成系列正整数之和:
例如正整数6有如下11种不同的划分,所有p(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
我们假设函数f(n,m):
n为要整数划分的数,m为划分中出现的最大加数
然后可以推出递归关系(反正我是推不出,只能理解了 (●—●))
① f ( 1 , m ) = 1 f(1,m)=1 f(1,m)=1, m ≥ 1 m\geq1 m≥1
当 n = 1 n=1 n=1时,不论m的值为多少( m > 0 m>0 m>0),只有一种划分即一个1。这很好理解,只要m选择比1大的数都会大于n。
② f ( n , 1 ) = 1 f(n,1)=1 f(n,1)=1, n ≥ 1 n\geq1 n≥1
当 m = 1 m=1 m=1时,不论n的值为多少( m > 0 m>0 m>0),只有一种划分即n个1。这也好理解,最大的加数为1,只能n个1相加才能等于n。
③ f ( n , m ) = f ( n , n ) f(n,m)=f(n,n) f(n,m)=f(n,n), m ≥ n m\geq n m≥n
最大加数m是不能超过整数划分的n的,因此只能更改最大整数m为整数划分的n。例如: f ( 3 , 5 ) = f ( 3 , 3 ) f(3,5)=f(3,3) f(3,5)=f(3,3)
④ f ( n , n ) = 1 + f ( n , n − 1 ) f(n,n)=1+f(n,n-1) f(n,n)=1+f(n,n−1)
正整数n的划分是由 s = n s=n s=n的划分和 s ≤ n − 1 s\leq n-1 s≤n−1的划分构成的。例如: f ( 6 , 6 ) = 1 + f ( 6 , 5 ) f(6,6)=1+f(6,5) f(6,6)=1+f(6,5)
⑤ f ( n , m ) = f ( n , m − 1 ) + f ( n − m , m ) , n > m > 1 f(n,m)=f(n,m-1)+f(n-m,m),n>m>1 f(n,m)=f(n,m−1)+f(n−m,m),n>m>1
个人觉得这个是最难的,感觉不好理解。
其解释为正整数n的最大加数s( s < m s
例如: f ( 6 , 4 ) = f ( 6 , 3 ) + f ( 2 , 4 ) = f ( 6 , 3 ) + f ( 2 , 2 ) f(6,4)=f(6,3)+f(2,4)=f(6,3)+f(2,2) f(6,4)=f(6,3)+f(2,4)=f(6,3)+f(2,2)
f ( 6 , 4 ) = 9 f(6,4)=9 f(6,4)=9 | f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7 | f ( 2 , 2 ) = 2 f(2,2)=2 f(2,2)=2 |
---|---|---|
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,3+1+1+1 2+2+2,2+2+1+1,2+1+1+1+1 1+1+1+1+1+1 |
4+2,4+1+1 |
个人认为这个例子对于理解很重要,首先我们可以看出 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7除了与 f ( 6 , 4 ) = 9 f(6,4)=9 f(6,4)=9少了4+2
和4+1+1
划分外,其他部分是一致的。而右侧的 f ( 2 , 2 ) = 2 f(2,2)=2 f(2,2)=2虽然并不真正包含加数4,但是 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7缺少的虽然包含整数4,但4不需要进行划分(划分部分已经就不含有4了),所以划分的整数2(即 n − m n-m n−m),则2的划分次数和 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7缺少的划分刚好相等。
此处我们只需要考虑次数,而不需考虑真正的划分加法序列,因此以总次数为中心。
综上递归方程为:
f ( n , m ) = { 1 n = 1 , m = 1 f ( n , n ) n < m 1 + f ( n , n − 1 ) n = m f ( n , m − 1 ) + f ( n − m , m ) n > m > 1 f(n,m)=\begin{cases} 1 & n = 1,m = 1 \\ f(n,n) & n < m \\ 1+f(n,n-1) & n = m \\ f(n,m-1)+f(n-m,m) & n > m > 1 \end{cases} f(n,m)=⎩⎪⎪⎪⎨⎪⎪⎪⎧1f(n,n)1+f(n,n−1)f(n,m−1)+f(n−m,m)n=1,m=1n<mn=mn>m>1
#include
using namespace std;
int split(int n,int m)
{
if(n == 1 || m == 1) return 1;
else if(n < m) return split(n,n);
else if(n == m) return split(n,n-1) + 1;
else return split(n,m-1)+split(n-m,m);
}
int main()
{
int n;
printf("输入划分数:");
scanf("%d",&n);
printf("整数划分为:%d\n",split(n,n));
return 0;
}
6
11
第一次看见整数划分是在《数据结构1800题》里面,其中算法大多苦涩难懂。看到这一题时是一个填空题,刚好都是递归方程的填空。之前没接触过,看着有些懵。在此看时才明白是怎么回事。
我相信学习是一个迭代的过程,只要不断进步不断努力就好!