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;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    【0003】与随机数有关的一些问题
    【0001】排序法与查找方式
    【0002】斐波那契数列,迷宫,汉诺塔
    【0001】C程序的编译过程
    django学习——request.POST.get(‘key’) 、 request.GET.get('key', '')
    django 删除数据库表后重新同步的方法
    Django链接mysql数据库报错1064
    sql练习题
    jmeter连接数据库
    购物车程序练习
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/12795353.html
Copyright © 2011-2022 走看看