您的位置:首页 > 其它

Stirling数。。

2015-10-31 00:18 369 查看

第一类 Stirling数。。

S(n, k) 存在正负。。其绝对值表示将n个数分为k个环排列的数目。。

递推公式

S(n, 0) = 0; n >= 1;

S(n, n) = 1; n >= 0;

s(n, k) = s(n - 1, k - 1) + (n - 1) * s(n - 1, k) , 1 <= k <= n - 1 //第k个数自成环,前n - 1个成环 + 将第个k数插入到前n - 1成环序列中

hdu 3625

题目大意:n个房间,每个房间都放有一把钥匙,1号钥匙对应1号门。。所有门都关着。。。计算最少的破门数(一号门不能破)

计算环排列数。。减去1号钥匙对应1号门的环排列数。。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <cctype>
#include <ctime>
#define MAX 0x3f3f3f3f
#define LL __int64
#define MOD (100)
#define N (20 + 1)

using namespace std;

LL s

, fn
;

void init()
{
memset(s, 0, sizeof(s));
for (int i = 1; i < N; i++)
{
s[i][i] = 1;
}

for (int i = 2; i < N; i++)
{
for (int j = 1; j <= i - 1; j++)
{
s[i][j] = s[i - 1][j - 1] + (i - 1) * s[i - 1][j];
}
}

fn[1] = fn[0] = 1;
for (int i = 2; i < N; i++)
{
fn[i] = i * fn[i - 1];
}

}

int main()
{
int T;
scanf("%d", &T);

init();

while (T--)
{
int n, k;
scanf("%d%d", &n, &k);

LL ans = 0;
for (int i = 1; i <= k; i++)
{
ans += s
[i] - s[n - 1][i - 1];
}

printf("%.4lf\n", 1.0 * ans / fn
);
}
}


hdu 4372

题目大意:有N座房子。。高度分别为1~N。。向前看能看到F座。。向后看能看到B座。。。求排列数。。。

第二类 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) + k * S(n - 1, k);

例:将n个有区别的球放入k个无标号的盒子中(n >= k >= 1, 且盒子不允许为空)的方案数为Stirling数。。。

推导:设有n个不同的球,分别为b1, b2, …bn, 从中取出一个球bn, bn的方法有两种。。。

1. bn 独占一个盒子, 剩下的球放在k-1个盒子里。。。方案数为S(n - 1, k - 1);

2. bn与别的球占同一个盒子。。方案数为k * S(n - 1, k);

LL s[N+2][N+2] = {1}, bell[N+2];

void init()
{
for (int i = 1; i <= N; i++)
{
s[i][0] = 0;
s[i][i] = 1;
for(int j = 1; j < i; j++)
{
s[i][j] = (s[i-1][j-1] + j * s[i-1][j]) % MOD;
}
}

for (int i = 1; i <= N; i++)
{
bell[i] = 0;
for (int j = 0; j <= i; j++)
{
bell[i] = (bell[i] + s[i][j]) % MOD;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息