将一个正整数N 划分为一系列的 正整数之和:
N = N1 + N2 + . . . + Nk;
其中,N1>=N2>=N3 .... >=Nk ,(k>=1) , 改表示称为 正整数N 的一个划分; 不同 划分方式 的种类个数成为划分数 。
例如: 将 N=3 划分:
3;
2+1;
1+1+1
在对正整数N 的所有划分中, 将最大加数N1 不大于M 的划分数记为 Q(N , M);
例如 对于 3 的划分中,我们定义 M=1, 则表示, 对于 3 的划分 最大加数 N1<=1 。
则可以建立如下的递归关系: 注下面的 n 为待划分的正整数N , m 为 最大划分数 N1
(1)当 n = 1 时 Q(n , m) = 1 只能划分成 1
(2)当 m = 1 时 Q(n , m) = 1 只能划分为 1
(3)当 n < m 时 Q(n , m) = Q(n , n) , 例如 对于 3 的划分 , 将 M=4 ,它只会分成(3) (2+1) (1+1 +1)
此次, 最大的划分数N1肯定 不会 超过 N 。
(4)当n = m 时 Q(n , m) = 1 + Q(n , n-1 ) ; 将问题分为两类 子问题, 即 最大划分数 为 n 的情况 和 n-1 的情况。
例如 n = m =3 , Q(3 , 3) = 1 + Q(3, 2) ,这里的 1 就是 最大划分数 N1=N =3 这种情况
(5)当 n> m 时 Q(n , m) = Q(n, m-1) + Q(n-m , m) ;如果 划正整数N 比 最大划分数N1大 的话, 我们可以按照 m-1 划分, 剩下的部分 按照 m 划分 。 直接进行 m 划分 的, 或许会造成 n-m 部分中含有 不小于 m 的部分。所以 我现 进行 m-1 划分, 在对 剩下的部分 进行 m 划分, 如此 划分下去, 我就可以保证 所有的划分数中 最大划分数 不大于 m .
例如 n=4, m= 2 ; Q(5 , 2 ) = Q(5,1) + Q( 3 , 2) ; 其中 Q(5 , 1) =1 ; 对于 Q(3 , 2) = Q(3 , 1) + Q(1 , 2) ; 所以 Q(5, 2) = 3 .
//当 n=1 , m=1 时 是能 分成 1 所以 q(1,1)=1
//当 n<m 时 即为不大于 n 的划分 即 q(n,n) , 所以 n<m 时 q(n,m) = q(n,n)
//当 n=m 时 情况 1 : 划分为 n , 情况2 划分为 不大于 n-1 ,即 q(n,n-1) , 所以 所以 n=m 时 q(n,m) = 1 + q(n,n-1)
//当 n>m 时 情况 1 :按照不大于 m-1,情况2(剩下的 n-m 有可能大于 m),所以将剩下的数在按照 不大于 m 划分(也即总划分中包含m 的情况) 所以 n>m q(n,m)= q(n,m-1) + q(n-m,m);
//求出一个数n 不大于 m 的划分数
#include<iostream>
#include<cstdio>
using namespace std;
int Q(int n,int m)
{
if(n==1||m==1)
return 1;
if(n<m)
return Q(n,n);
if(n==m)
return 1+Q(n,n-1);
if(n>m&&m>1)
return Q(n,m-1)+Q(n-m,m);
}
int main()
{
int n,m;
cin>>n>>m;
cout<<Q(n,m);
return 0;
}
递归输出一个正整数N 的不同 划分数:
例如 :正整数N=3的不同划分:
3
2+1
1 + 1 +1
#include<iostream>
#include<cstdio>
using namespace std;
int mak[300];
int n;
void Integer_Divide(int now_n,int k,int pre)
{
if(now_n>n)
return ;
if(now_n==n)
{
cout<<n<<" = ";
for(int i=0;i<k-1;i++)
cout<<mak[i]<<"+";
cout<<mak[k-1]<<endl;
}
else
{
for(int j=pre;j>=1;j--){
mak[k]=j;
now_n+=j;
Integer_Divide(now_n,k+1,j);
now_n-=j;//恢复现场
}
}
}
int main()
{
cin>>n;
Integer_Divide(0,0,n);
}