集合的划分(递推)

集合的划分

时间限制: 1 Sec  内存限制: 128 MB
提交: 9  解决: 8
[提交][状态][讨论版][命题人:quanxing]

题目描述

设S是一个具有n个元素的集合,S=⟨a1a2,……an⟩S=⟨a1,a2,……,an⟩ ,现将S划分成k个满足下列条件的子集合S1S2,……SkS1,S2,……,Sk ,且满足:

1.Si ≠ ∅

2.Si ∩ Sj = ∅            (1≤i,j≤k  i≠j)

3.S1 ∪ S2 ∪ S3 ∪ … ∪ Sk = S

则称S1S2,……SkS1,S2,……,Sk 是集合S的一个划分。它相当于把S集合中的n个元素a1a2,……ana1,a2,……,an 放入k个(0<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1a2,……ana1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。

输入

给出n和k。

输出

n个元素a1a2,……ana1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。

样例输入

10 6

样例输出

22827

/*对于任一元素a(n)有两种情况 1:a(n)存在于k个子集中,那么我们只需要把剩下的a(1)-a(n-1)划分到k-1个子集 则digui(i-1,j-1) 
2.a(n)不是k个子集中的一个,那么a(n)必定和其他元素构成子集那么就是把a(1)-a(n-1)划分为k个子集然后把a(n) 
任意放入一个子集则有j*digui(i-1,j) 
递归关系就是:digui(i-1,j-1)+j*digui(i-1,j)*/  
#include <iostream>  
#include <stdio.h>  
using namespace std;  
int digui(int i,int j)  
{  
    if(j==0||i<j) //如果没有盒子或者盒子个数大于球的个数  
        return 0;  
    else if(j==1||j==i)//如果只有一个盒子或者球和盒子的个数相等  
        return 1;  
    else if(j>0&&i>j)  
        return digui(i-1,j-1)+j*digui(i-1,j);  
  
}  
int main ()  
{  int n,k;  
while(scanf("%d%d",&n,&k)!=EOF)  
{  
    cout<<digui(n,k)<<endl;  
}  
    return 0;  
} 
 
原文地址:https://www.cnblogs.com/caiyishuai/p/13271113.html