1315:【例4.5】集合的划分
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 8438 通过数: 3559
【题目描述】
设S是一个具有n个元素的集合,S=⟨a1,a2,……,an⟩,现将S划分成k个满足下列条件的子集合S1,S2,……,Sk ,且满足:
1.Si≠∅
2.Si∩Sj=∅ (1≤i,j≤k,i≠j)
3.S1∪S2∪S3∪…∪Sk=S
则称S1,S2,……,Sk是集合S的一个划分。它相当于把S集合中的n个元素a1,a2,……,an 放入k个(0<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。
【输入】
给出n和k。
【输出】
n个元素a1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。
【输入样例】
10 6
【输出样例】
22827
思路:
{an}是k子集合中的一个,于是我们只要把a1,a2,an-1划分k-1个子集,划分的个数共有s(n-1,k-1)
{an}不是k个子集中的任意一个子集,则an必与其他元素构成一个子集,则问题相当于先把a1,a2,a3…an-1划分成k个子集,这 种情况下划分数共有s(n-1,k)个,然后在把an加入到k个子集中的任意一个中去,共有k种加入方式,这样对于an的每一种加入方式,都可以使集合划分为k个子集,因此根据乘法原理,划分数共有k*s(n-1,k)个
#include<iostream>
#include<cstring>
using namespace std;
long long s(int n,int k)
{
if((n<k)||(k==0)) return 0;
if((k==1)||(k==n)) return 1;
return s(n-1,k-1)+k*s(n-1,k);
}
int main()
{
int n,k;
cin>>n>>k;
cout<<s(n,k)<<endl;
return 0;
}