zoukankan      html  css  js  c++  java
  • [2015hdu多校联赛补题]hdu5378 Leader in Tree Land

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5378

    题意:给你一棵n个结点的有根树。因为是有根树,那么每个结点可以指定以它为根的子树(后面讨论的子树都是这个)。现在我们把标号从1到n的n个minister派驻到这些结点上面(每个结点派驻一人),并规定任一子树中编号最大的minister 为该子树的领导,问你存在多少个不同的领导

    解:

    引用官方题解:

    可以用求概率的思想来解决这个问题。令以i号节点为根的子树为第i棵子树,设这颗子树恰好有sz[i]个点。那么第i个点是第i棵子树最大值的概率为1/sz[i],不是最大值的概率为(sz[i]-1)/sz[i]。现在可以求解恰好有k个最大值的概率。
    
    令dp[i][j]表示考虑编号从1到i的点,其中恰好有j个点是其子树最大值的概率。 很容易得到如下转移方程:dp[i][j]=dp[i-1][j]*(sz[i]-1)/sz[i]+dp[i-1][j-1]/sz[i]。这样dp[n][k]就是所有点中恰好有k个最大值的概率。
    
    题目要求的是方案数,用总数n!乘上概率就是答案。计算的时候用逆元代替上面的分数即可
    
     1 /*
     2  * Problem: hdu5378  Leader in Tree Land
     3  * Author:  SHJWUDP
     4  * Created Time:  2015/8/12 星期三 20:17:31
     5  * File Name: 1006.cpp
     6  * State: Accepted
     7  * Memo: 概率dp,乘法逆元
     8  */
     9 #include <iostream>
    10 #include <cstdio>
    11 #include <vector>
    12 #include <cstring>
    13 #include <algorithm>
    14 
    15 using namespace std;
    16 
    17 const int MOD=1e9+7;
    18 
    19 struct Edge {
    20     int u, v;
    21 };
    22 
    23 int n, k;
    24 vector<Edge> edges;
    25 vector<vector<int> > G;
    26 vector<int> siz, inv;    ///siz[i]*inv[i]=1(mod 1e9+7)
    27 void init() {
    28     edges.clear();
    29     G.assign(n+1, vector<int>(0));
    30     siz.resize(n+1);
    31     inv.resize(n+1);
    32 }
    33 void addEdge(int u, int v) {
    34     edges.push_back((Edge){u, v});
    35     G[u].push_back(edges.size()-1);
    36 }
    37 int pow_mod(long long x, int n, int mod) {
    38     long long res=1;
    39     while(n) {
    40         if(n & 1) res=res*x%mod;
    41         x=x*x%mod;
    42         n>>=1;
    43     }
    44     return res;
    45 }
    46 void dfs(int u, int fa) {
    47     siz[u]=1;
    48     for(int i : G[u]) {
    49         Edge & e=edges[i];
    50         if(e.v==fa) continue;
    51         dfs(e.v, u);
    52         siz[u]+=siz[e.v];
    53     }
    54 }
    55 int main() {
    56 #ifndef ONLINE_JUDGE
    57     freopen("in", "r", stdin);
    58     //freopen("out", "w", stdout);
    59 #endif
    60     int T, now=0;
    61     scanf("%d", &T);
    62     while(T--) {
    63         scanf("%d%d", &n, &k);
    64         init();
    65         for(int i=0; i<n-1; i++) {
    66             int a, b;
    67             scanf("%d%d", &a, &b);
    68             addEdge(a, b);
    69             addEdge(b, a);
    70         }
    71         dfs(1, -1);
    72         for(int i=1; i<=n; i++) inv[i]=pow_mod(siz[i], MOD-2, MOD);    //求siz[i]的乘法逆元
    73         vector<vector<long long> > f(n+1, vector<long long>(n+1, 0));
    74         f[0][0]=1;
    75         for(int i=1; i<=n; i++) {
    76             for(int j=0; j<=k; j++) {
    77                 f[i][j]+=f[i-1][j]*(siz[i]-1)%MOD*inv[i]%MOD;
    78                 if(j>0)f[i][j]+=f[i-1][j-1]*inv[i]%MOD;
    79                 f[i][j]%=MOD;
    80             }
    81         }
    82         long long ans=f[n][k];
    83         for(int i=1; i<=n; i++) {
    84             ans=(ans*i)%MOD;
    85         }
    86         printf("Case #%d: ", ++now);
    87         printf("%I64d
    ", ans);
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    Eclipse汉化后怎么改回英文版 (中文 改 英文)
    解决android中Layout文件下的xml文件配好后,R类中不能自动生成相应代码
    Android SDK离线安装
    Windows环境下Android Studio v1.0安装教程
    Eclipse调试Bug的七种常用技巧
    博客开通了
    Android常见的按钮监听器实现方式
    用setTimeout实现在DOM上(通常是菜单栏)鼠标停留一段时间才执行相应的操作
    Javascript模块模式学习分享
    Oracle数据库逻辑存储结构管理
  • 原文地址:https://www.cnblogs.com/shjwudp/p/4725795.html
Copyright © 2011-2022 走看看