考前浮躁,感觉没有一点刷高数的动力,更别提思修了。。我现在好想赶紧考完试
毕竟
还是水oj令我感到充实
做完1009之后 1010停滞了好久 1011更是停滞了很久,它上面的题下面的题都ac了,都有大大的Y,只有它没有,我很气愤
于是我想百度一下, 师哥说 这是第二类斯特林数, 反正浮躁也是浮躁
不如看一看,万一懂了呢
比愣神强。。。
1011.盒子与球
Description
现有r个互不相同的盒子和n个互不相同的球,要将这n个球放入r个盒子中,且不允许有空盒子。则有多少种放法?
Input
n, r(0 <= n, r <= 10)。
Output
有多少种放法。
Sample Input
3 2
Sample Output
6
第二类斯特林数:
第二类Stirling数是把包含n个元素的集合划分为正好k个非空子集的方法的数目。
递推公式为: S(n,k)=0; (n<k||k=0) S(n,n) = S(n,1) = 1,
S(n,k) = S(n-1,k-1) + kS(n-1,k).
考虑第p个物品,p可以单独构成一个非空集合,此时前p-1个物品构成k-1个非空的
不可辨别的集合,方法数为S(p-1,k-1);
也可以前p-1种物品构成k个非空的不可辨别的集合,
第p个物品放入任意一个中,这样有k*S(p-1,k)种方法。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
int sum[12][12];
int jiec[12];
int main()
{
jiec[0] = 1, jiec[1] = 1, jiec[2] = 2;
for(int i = 3; i <= 10; i ++)
{
jiec[i] = jiec[i - 1] * i;//阶乘的大小,数据不大提前算出来
}
for(int i = 0; i <= 10; i ++)
for(int j = 0; j <= 10; j ++)
{
if(j == 0 || j > i)sum[i][j] = 0;//i为球的个数, j为盒子的个数,盒子比球多或者没有盒子的情况都是无解的
else if(i == j || j == 1) sum[i][j] = 1;//S(n, n)=S(n, 1)=1
else sum[i][j] = sum[i - 1][j - 1] + j * sum[i - 1][j];//此处运用第二类斯特林数递推公式 S(n,k) = S(n-1,k-1) + kS(n-1,k)
}
int m, n;
while(cin>>m>>n)
{
cout<<jiec[n] * sum[m][n]<<endl;//结果就是这样,推导很麻烦不想看,k! *S(p,k) 计数的是把p元素集合划分到k个不同的的盒子里且没有空盒子的划分个数
而k*S(p, k)是k个相同的盒子的情况。
}
return 0;
}
水题令我快乐
还有第一类斯特林数和bell数,以后碰见再整理
本文探讨了利用第二类斯特林数解决盒子与球的排列组合问题,并给出了具体的算法实现,包括递推公式和样例输入输出。
778

被折叠的 条评论
为什么被折叠?



