zoukankan      html  css  js  c++  java
  • hdu2643 Rank

    题面

    题目链接

    hdu-2643

    题目大意

    有 n 位选手参加比赛,每个选手有一个排名

    排名可能出现并列的情况,问一共有多少种排名情况

    解题思路

    第二类Stirling

    先把排名当做集合,排名为 1 的人数即放入集合 1 的人数

    再把集合等效化,即把集合 1 和集合 2 看作是完全相同的集合

    那么此时题目就可以转换为将 n 个物品放入若干个完全相同的集合的方案数

    可得递推式 dp[i][j] 表示前 i 个物品用了 j 个完全相同的集合的方案数

    其中 dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] * j : 

    ①、前 i - 1 个物品构成了 j - 1 个集合,第 i 个物品构成第 j 个集合

    ②、前 i - 1 个物品构成了 j 个集合,则第 i 个物品可以放入 1 ~ j 个集合

    那么 ans =  ∑ dp[n][i] 

    然而这只是集合等效化后的答案,实际上当我们使用的 i 个集合应该是完全不同的

    所以为了恢复等效化我们还需要乘上 i 的全排列即 i!

    那么现在 ans = ∑ dp[n][i] * i!

    AC_Code

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N = 1e3 + 10 , mod = 20090126;
    int dp[N][N] , fac[N];
    void init()
    {
        fac[0] = 1 , dp[1][1] = 1 , dp[0][0] = 1;
        for(int i = 1 ; i <= 100 ; i ++)
        {
            fac[i] = fac[i - 1] * i % mod;
            for(int j = 1 ; j <= i ; j ++)
            {
                dp[i][j] = dp[i - 1][j] * j + dp[i - 1][j - 1];
                dp[i][j] %= mod;
            }
        }
    }
    signed main()
    {
        init();
        int t ;
        cin >> t ;
        while(t --)
        {
            int n , ans = 0;
            cin >> n ; 
            for(int i = 1 ; i <= n ; i ++) ans += dp[n][i] * fac[i] , ans %= mod;
            cout << ans << '
    ';
        }
        return 0;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    在路上——7月英语
    Today is a special day for English Topic
    三级网络-不单单是学知识
    停下是为了更好的出发
    量变引发质变--【2015年计算机年终总结】
    这个月,小美很忙
    一个人牛逼不如一群人一起牛逼——致我最亲爱的程序员
    掀起你的盖头来--【2015年英语年终总结】
    平凡之路之小美
    小美的猴年年中总结,挪不开眼~
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/12795353.html
Copyright © 2011-2022 走看看