划分问题
#include <stdio.h>
/*******************************************************************/
/*整数划分问题:
**将正整数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。
*/
/************************************************************************/
/************************************************************************/
/*算法:
**记q(n,m)表示n的最大加数n1不大于m的划分个数,则有:
** |- 1 ,n=1,m=1
**q(n,m)=| q(n,n) ,n<m
** | 1+q(n,n-1),n=m ,n的划分由n1=n的划分和n1<=n-1的划分组成
** |_ q(n-m,m)+q(n,m-1),n>m>1,n的最大加数n1不大于m的划分由n1=m的划分和n1<=m-1的划分组成
*/
/*******************************************************************/
int int_partion(int n,int m)
{
if(n==1||m==1)
return 1;
else if(n<m)
return int_partion(n,n);
else if(n==m)
return 1+int_partion(n,n-1);
else
return int_partion(n-m,m)+int_partion(n,m-1);
}
/*非递归算法*/
#define N 6
int S[N+1][N+1];
int int_partion_2(int n,int m)
{
int i,j;
for (i=1;i<=n;i++)
{
S[i][1]=1;
S[1][i]=1;
}
for (i=2;i<=n;i++)
{
for (j=2;j<=m;j++)
{
if(i==j)
S[i][j]=1+S[i][i-1];
else if(i<j)
S[i][j]=S[i][i];
else
S[i][j]=S[i-j][j]+S[i][j-1];
}
}
return S[n][m];
}
/*******************************************************************/
/*集合划分问题:
**n个元素{1,2,,n}可以划分为多少个非空子集。该值实际上为Bell数,记为B(n)。
**例如:{1,2,3}的划分:
**{{1,2,3}}, {{1,2},{3}}, {{1,3},{2}}, {{1},{2,3}}
*/
/*******************************************************************/
/************************************************************************/
/*算法:
**记s(n,m)表示n个元素集合可以划分为m个非空子集的数量,该数实际上是Stirling数,则有:
**s(n,m)=m*s(n-1,m)+s(n-1,m-1); s(n,n+1)=0,s(n,0)=0,s(0,0)=1。
**显然:B(n)=s(n,1)+s(n+2)++s(n,n)
*/
/*******************************************************************/
//计算stirling数
int stirling(int n,int m)
{
int min,i,j;
S[0][0]=1;
for (i=1;i<=n;i++)
S[i][0]=0;
for(i=0;i<n;i++)
S[i][i+1]=0;
for (i=1;i<=n;i++)
{
if(i<m)
min=i;
else
min=m;
for(j=1;j<=min;j++)
S[i][j]=j*S[i-1][j]+S[i-1][j-1];
}
return S[n][m];
}
//计算bell数
int bell(int n)
{
int num=0;
stirling(n,n);
for (int i=1;i<=n;i++)
{
num+=S[n][i];
}
return num;
}
int main()
{
int n=4,m=2;
//printf("%d pation numbers are:%d\n",n,int_partion_2(n,n));
printf("%d,%d sirling number is:%d\n",n,m,stirling(n,m));
printf("%d bell number is:%d\n",n,bell(n));
return 0;
}
/*******************************************************************/
/*整数划分问题:
**将正整数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。
*/
/************************************************************************/
/************************************************************************/
/*算法:
**记q(n,m)表示n的最大加数n1不大于m的划分个数,则有:
** |- 1 ,n=1,m=1
**q(n,m)=| q(n,n) ,n<m
** | 1+q(n,n-1),n=m ,n的划分由n1=n的划分和n1<=n-1的划分组成
** |_ q(n-m,m)+q(n,m-1),n>m>1,n的最大加数n1不大于m的划分由n1=m的划分和n1<=m-1的划分组成
*/
/*******************************************************************/
int int_partion(int n,int m)
{
if(n==1||m==1)
return 1;
else if(n<m)
return int_partion(n,n);
else if(n==m)
return 1+int_partion(n,n-1);
else
return int_partion(n-m,m)+int_partion(n,m-1);
}
/*非递归算法*/
#define N 6
int S[N+1][N+1];
int int_partion_2(int n,int m)
{
int i,j;
for (i=1;i<=n;i++)
{
S[i][1]=1;
S[1][i]=1;
}
for (i=2;i<=n;i++)
{
for (j=2;j<=m;j++)
{
if(i==j)
S[i][j]=1+S[i][i-1];
else if(i<j)
S[i][j]=S[i][i];
else
S[i][j]=S[i-j][j]+S[i][j-1];
}
}
return S[n][m];
}
/*******************************************************************/
/*集合划分问题:
**n个元素{1,2,,n}可以划分为多少个非空子集。该值实际上为Bell数,记为B(n)。
**例如:{1,2,3}的划分:
**{{1,2,3}}, {{1,2},{3}}, {{1,3},{2}}, {{1},{2,3}}
*/
/*******************************************************************/
/************************************************************************/
/*算法:
**记s(n,m)表示n个元素集合可以划分为m个非空子集的数量,该数实际上是Stirling数,则有:
**s(n,m)=m*s(n-1,m)+s(n-1,m-1); s(n,n+1)=0,s(n,0)=0,s(0,0)=1。
**显然:B(n)=s(n,1)+s(n+2)++s(n,n)
*/
/*******************************************************************/
//计算stirling数
int stirling(int n,int m)
{
int min,i,j;
S[0][0]=1;
for (i=1;i<=n;i++)
S[i][0]=0;
for(i=0;i<n;i++)
S[i][i+1]=0;
for (i=1;i<=n;i++)
{
if(i<m)
min=i;
else
min=m;
for(j=1;j<=min;j++)
S[i][j]=j*S[i-1][j]+S[i-1][j-1];
}
return S[n][m];
}
//计算bell数
int bell(int n)
{
int num=0;
stirling(n,n);
for (int i=1;i<=n;i++)
{
num+=S[n][i];
}
return num;
}
int main()
{
int n=4,m=2;
//printf("%d pation numbers are:%d\n",n,int_partion_2(n,n));
printf("%d,%d sirling number is:%d\n",n,m,stirling(n,m));
printf("%d bell number is:%d\n",n,bell(n));
return 0;
}