题目:n个元素的集合{1,2,.....,n},可以划分为若干个非空子集,如,当n=4时,集合{1,2,3,4}可以划分为15个不同的非空子集如下:
由4个子集组成:
{{1},{2},{3},{4}}
由3个子集组成:
{{1,2},{3},{4}}
{{1,3},{2},{4}}
{{1,4},{2},{3}}
{{2,3},{1},{4}}
{{2,4},{1},{3}}
{{3,4},{1},{2}}
由2个子集组成:
{{1,2},{3,4}}
{{1,3},{2,4}}
{{1,4},{2,3}}
{{1,2,3},{4}}
{{1,2,4},{3}}
{{1,3,4},{2}}
{{2,3,4},{1}}
由1个子集组成:
{{1,2,3,4}}
给定正整数n和m,计算出n个元素的集合{1,2,...,n}可以划分为多少个不同的由m个非空子集组成的集合?
Thinking:
设F(n,m)为n个元素集合{1,2,...,n}中划分出m个非空子集组成的集合个数 (1<=m<=n)
如:
F(2,1)=1, {{1,2}}
F(2,2)=1; {{1},{2}}
F(3,1)=1, {{1,2,3}}
F(3,2)=3, {{1,2},{3}}, {{1,3},{2}}, {{2,3},{1}}
F(3,3)=1; {{1},{2},{3}}
F(4,1)=1 {{1,2,3,4}}
F(4,2)=7, {{1,2},{3,4}}, {{1,3},{2,4}}, {{1,4},{2,3}}, {{1,2,3},{4}}, {{1,2,4},{3}}, {{1,3,4},{2}}, {{2,3,4},{1}}
F(4,3)=6, {{1,2},{3},{4}}, {{1,3},{2},{4}}, {{1,4},{2},{3}}, {{2,3},{1},{4}}, {{2,4},{1},{3}}, {{3,4},{1},{2}}
F(4,4)=1, {{1},{2},{3},{4}}
接下来,演示F(n,m)的形成过程
F(3,2)形成过程:
在F(2,1)中,添加一个元素,即为
{{1,2}}->{{1,2},{3}}
在F(2,2)中,添加一个元素,且不改变m,即为
{{1},{2}}->{{1,3},{2}} || {{1},{2,3}}
F(4,2)形成过程:
在F(3,1)中,添加一个元素,即为
{{1,2,3}}->{{1,2,3},{4}}
在F(3,2)中,添加一个元素,且不改变m,即为
{{1,2},{3}}->{{1,2,4},{4}} || {{1,2},{3,4}}
{{1,3},{2}}->{{1,3,4},{2}} || {{1,3},{2,4}}
{{2,3},{1}}->{{2,3,4},{1}} || {{2,3},{1,4}}
F(4,3)形成过程:
在F(3,2)中,添加一个元素,即为
{{1,2},{3}}->{{1,2},{3,4}}
{{1,3},{2}}->{{1,3},{2,4}}
{{2,3},{1}}->{{2,3},{1,4}}
在F(3,3)中,添加一个元素,且不改变m,即为
{{1},{2},{3}}->{{1,4},{2},{3}} || {{1},{2,4},{3}} || {{1},{2},{3,4}}
看完了F(3,2),F(4,2),F(4,3)的形成过程,大概可以体会到一点味道了,若要求F(n,m),则要先求F(n-1,m)和F(n-1,m-1).
再想想,发现有规律如下:
F(n,m)=F(n-1,m-1)+m*F(n-1,m);(n>=2,m>=2)
还有一些易知条件:
F(n,1)=F(n,n)=1; (n>1)
F(n,0)=0;
F(n,m)=0; (m>n)
code:
#include<iostream>
using namespace std;
double arr[250][250];
int n;//n最多只能输入200左右 否则会overflow
void init()
{
for(int i=1;i<=n;i++)
{
arr[i][1]=1;
arr[i][i]=1;
}
}
void function()
{
for(int i=2;i<=n;i++)
for(int j=2;j<=i;j++)
arr[i][j]=arr[i-1][j-1]+j*arr[i-1][j];
}
void output()
{
for(int i=1;i<=n;i++)
cout<<"F("<<n<<","<<i<<") : "<<arr[n][i]<<endl;
}
int main()
{
cin>>n;
init();
function();
output();
return 0;
}