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 ", sum * a[n][r]); return 0; }