集合的划分(递归)

本文介绍了一种计算给定集合S的元素按指定条件划分为k个非空子集的方案数S(n,k),并提供了使用动态规划求解的AC代码,着重于理解递归公式和对1e9+7取余操作的应用。

题目描述

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

则称S1,S2,……,Sk是集合S的一个划分。它相当于把S集合中的n个元素a1 ,a2,……,an 放入k个(0<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1 ,a2 ,……,an 放入k个无标号盒子中去的划分数S(n,k)对1e9+7取余之后的值。

输入n,k

输出S(n,k) mod 1e9+7 的值

样例输入 Copy

23 7

样例输出 Copy

968438818

AC代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<string>
const long long MOD=1e9+7;
using namespace std;
long long n,m,k;
long long dp(int n,int k)//i个数放进k个集合的总方案数 
{
	if(n==0 || n<k)//数小于集合数||没有数了,不存在方案 
		return 0;
	if(n==k || k==1)//因为无标号,所以哪个盒子无所谓,盒子数=数,一个盒子,都是一种情况 
		return 1; 
	return (dp(n-1,k-1)+k*dp(n-1,k))%MOD;//要么单独是一个集合,所以相当于少一个数少一个集合
	//要么这个数是从k个集合中取出来的,所以有k种选择(随便进哪个集合) 
	//相加的总和就是现在的方案数 
}
int main()
{
	cin>>n>>k;
	cout<<dp(n,k)<<endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值