• 集合的划分(递推)


    集合的划分

    时间限制: 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;  
    } 
     
  • 相关阅读:
    [BZOJ1691][Usaco2007 Dec]挑剔的美食家
    [BZOJ1056][BZOJ1862][HAOI2008][Zjoi2006]排名系统
    [POJ2892]Tunnel Warfare
    [BZOJ1588][HNOI2002]营业额统计
    [BZOJ1503][NOI2004]郁闷的出纳员
    [HDU4507]吉哥系列故事——恨7不成妻
    [codeforces 55]D. Beautiful numbers
    [HDU3709]Balanced Number
    [COJ0528]BJOI幸运数
    [TimusOJ1057]Amount of Degrees
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/13271113.html
Copyright © 2020-2023  润新知