zoukankan      html  css  js  c++  java
  • HDOJ 4372 第一类斯特林数

    链接:

    http://acm.split.hdu.edu.cn/showproblem.php?pid=4372

    题意:

    有一系列的楼房,高度从1~n,然后从左侧看能看到f个楼房,右侧看能看到b个楼房,问有多少个方案数满足。

    题解:

    首先我们知道一个结论:n的环排列的个数与n-1个元素的排列的个数相等,因为P(n,n)/n=(n-1)!。

    可以肯定,无论从最左边还是从最右边看,最高的那个楼一定是可以看到的.

    假设最高的楼的位置固定,最高楼的编号为n,那么我们为了满足条件,可以在楼n的左边分x-1组,右边分y-1组,

    且用每组最高的那个元素代表这一组,那么楼n的左边,从左到右,组与组之间最高的元素一定是单调递增的,

    且每组中的最高元素一定排在该组的最左边,每组中的其它元素可以任意排列(相当于这个组中所有元素的环排列)。右边反之亦然。

    然后,可以这样考虑这个问题,最高的那个楼左边一定有x-1个组,右边一定有y-1个组,且每组是一个环排列,

    这就引出了第一类Stirling数(n个人分成k组,每组内再按特定顺序围圈的分组方法的数目)。

    我们可以先把n-1个元素分成x-1+y-1组,然后每组内部做环排列。再在所有组中选取x-1组放到楼n的左边。所以答案是

    ans(n, f, b) = C[f + b - 2][f - 1] * S[n - 1][f + b - 2];

    代码:

    31 ll stir[MAXN][MAXN];
    32 ll C[MAXN][MAXN];
    33 
    34 void init() {
    35     stir[1][0] = 0;
    36     stir[1][1] = 1;
    37     rep(i, 2, MAXN) rep(j, 1, i + 1)
    38         stir[i][j] = (stir[i - 1][j - 1] + (i - 1)*stir[i - 1][j]) % MOD;
    39     rep(i, 1, MAXN) {
    40         C[i][0] = C[i][i] = 1;
    41         rep(j, 1, i) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
    42     }
    43 }
    44 
    45 int main() {
    46     ios::sync_with_stdio(false), cin.tie(0);
    47     init();
    48     int T;
    49     cin >> T;
    50     while (T--) {
    51         int n, f, b;
    52         cin >> n >> f >> b;
    53         cout << C[f + b - 2][f - 1] * stir[n - 1][f + b - 2] % MOD << endl;
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    synchronized 关键字
    synchronized 关键字
    Linux IPC之共享内存
    链表的插入、删除
    链式队列的实现
    链栈的实现
    双色、三色排序问题
    memmove、memcpy、strcpy、memset的实现
    字符串中去掉多余的空格
    华为机试:从一个数组中选取不同的数(均小于10)组成一个最大的三位数
  • 原文地址:https://www.cnblogs.com/baocong/p/7622237.html
Copyright © 2011-2022 走看看