• 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;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    Heapsort 堆排序算法详解(Java实现)
    GIve Me A Welcome Hug!
    linux系统救援模式拯救mv libc.so.6文件后无法使用命令的悲剧
    RabbitMQ集群部署
    使用Xshell通过堡垒机登录服务器
    dubbo + zookeeper环境部署
    zookeeper集群部署
    zabbix-3.0.1 添加微信报警
    zabbix-3.0.1结合grafana绘图
    Centos7.2安装zabbix3.0.1简要
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/12795353.html
Copyright © 2020-2023  润新知