斯特兰数链接:https://www.cnblogs.com/owenyu/p/6724661.html
题目描述
现有 r 个互不相同的盒子和 n 个互不相同的球,要将这 n个球放入 r个盒子中,且不允许有空盒子。请求出有多少种不同的放法。
两种放法不同当且仅当存在一个球使得该球在两种放法中放入了不同的盒子。
输入格式
输入只有一行两个整数,分别代表 n和 r。
输出格式
输出一行一个整数代表答案。
输入输出样例
输入 #1复制
3 2
输出 #1复制
6
说明/提示
样例输入输出 1 解释
有两个盒子(编号为 1, 21,2)和三个球(编号为 1, 2, 3),共有六种方案,分别如下:
盒子编号 | 方案 1 | 方案 2 | 方案 3 | 方案 4 | 方案 5 | 方案 6 |
---|---|---|---|---|---|---|
盒子 1 | 小球 1 | 小球 2 | 小球 3 | 小球 2,,3 | 小球 1, 3 | 小球 1, 2 |
盒子 2 | 小球 2, 3 | 小球 1, 31,3 | 小球 1, 2 | 小球 1 | 小球 2 | 小球 3 |
数据规模与约定
对于 100% 的数据,保证0≤r≤n≤10,且答案小于 2^{31}。
思路:此处是将n个小球放到r个不同盒子里,等价于将n个·不同小球分成r个集合,又因为这些集合不同,所以乘以r!. 这里是第二类斯特兰数。状态转移方程为 f[i][j]=f[i-1][j-1]+j*f[i-1][j];
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,r,f[100][100]={1};
int fc(int n){
if(n==1) return 1;
else return n*fc(n-1);
}
int main(){
cin>>n>>r;
for(int i=1;i<=n;i++){//将n个球分成r个集合
for(int j=1;j<=r;j++){
f[i][j]=f[i-1][j-1]+j*f[i-1][j];
}
}
cout<<f[n][r]*fc(r);//因为盒子也各不相同,所以乘以盒子数的阶乘
return 0;
}