zoukankan      html  css  js  c++  java
  • 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
    ", sum * a[n][r]);
        return 0;
    }
  • 相关阅读:
    topcoder srm 681 div1
    topcoder srm 683 div1
    topcoder srm 684 div1
    topcoder srm 715 div1
    topcoder srm 685 div1
    topcoder srm 687 div1
    topcoder srm 688 div1
    topcoder srm 689 div1
    topcoder srm 686 div1
    topcoder srm 690 div1 -3
  • 原文地址:https://www.cnblogs.com/RootVount/p/11418879.html
Copyright © 2011-2022 走看看