SDNU 1011.盒子与球(斯特林函数)

Description

现有r个互不相同的盒子和n个互不相同的球,要将这n个球放入r个盒子中,且不允许有空盒子。则有多少种放法?

Input

n, r(0 <= n, r <= 10)。

Output

有多少种放法。

Sample Input

3 2

Sample Output

6

Source

 
思路:这道题用的是斯特林函数。
第一类斯特林函数:将 n 个不同元素构成m个圆排列,如果要将n + 1个元素构成m个圆排列,考虑第n + 1个元素:
                            (1)如果n个元素构成m - 1个圆排列,则第n + 1个元素独自构成一个圆排列:s(n, m - 1);
                            (2)如果n个元素构成m个圆排列,则第n + 1个元素插入任意元素的左边:n * s(n, m);
                              总和s(n + 1, m) = s(n, m - 1) + n * s(n, m)。
第二类斯特林函数:将n个不同的球放入m个无差别的盒子中,要求盒子非空,考虑第n + 1个元素:
                            (1)如果n个元素构成m - 1个集合,则第n + 1个元素就构成单独一个集合:s(n, m - 1);
                            (2)如果n个元素构成m个集合,则第n + 1个元素就查到任意一个集合:m * s(n, m);
                              总和s(n + 1, m) = s(n, m - 1) + m * s(n, m)。
 
但是题目要求是r个不同的盒子,r个不同盒子的排列就是 r!,所以最后的答案应该乘以r的阶乘。
#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define eps 1e-9

const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 100000 + 8;

int a[18][18];

int main()
{
    int n, r, sum = 1;
    memset(a, 0, sizeof(a));
    scanf("%d%d", &n, &r);
    a[1][1] = 1;
    for(int i = 2; i <= n; i++)
    {
        for(int j = 1; j <= r; j++)
        {
            a[i][j] = a[i - 1][j - 1] + a[i - 1][j] * j;
        }
    }
    for(int i = 1; i <= r; i++)
        sum *= i;
    printf("%d\n", sum * a[n][r]);
    return 0;
}

 

posted @ 2019-08-27 16:00  明霞  阅读(317)  评论(0编辑  收藏  举报