描述 Description
现有r个互不相同的盒子和n个互不相同的球,要将这n个球放入r个盒子中,且不允许有空盒子。问有多少种方法?
例如:有2个不同的盒子(分别编为1号和2号)和3个不同的球(分别编为1、2、3号),则有6种不同的方法:
1号盒子 1号球 1、2号球 1、3号球 2号球 2、3号球 3号球
2号盒子 2、3号球 3号球 2号球 1、3号球 1号球 1、2号球
输入格式 Input Format
两个整数,n和r,中间用空格分隔。(0≤n, r≤10)
输出格式 Output Format
一个整数,如题目描述
样例输入 Sample Input
3 2
样例输出 Sample Output
6
时间限制 Time Limitation
各个测试点1s
注释 Hint
第二类Stirling数。
看到这个题的时候我第一时间认为这是一个用挡板法然后求一下组合数。然后在看看题emmmm.......
这是不同的球和不同的盒子哇,好吧不会搞了.......
然后去学了学第二类Stirling数。第二类Stirling数实际上是集合的一个拆分,表示将n个不同的元素拆分成m个集合的方案数,记为 或者
公式就是如下了
这个第二类Stirling数就是用来求将n个不同元素分成m个集合的方案数了,所以这道题也是一个模板题
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int a[15][15];//当元素超过20的时候记得换成long long int main() { int n,r; cin>>n>>r; memset(a,0,sizeof(a)); for(int i=1;i<15;i++) a[i][1]=1; for(int i=2;i<15;i++) { for(int j=1;j<=i;j++) { a[i][j]=a[i-1][j-1]+j*a[i-1][j]; } } long long ans=1; for(int i=1;i<=r;i++) ans*=i; cout<<a[n][r]*ans<<endl; return 0; }