• [概率dp] hdu 5378 Leader in Tree Land


    题意:

    给你一颗以1位根节点的树。我们定义对于每一个子树,节点权值最大的权值记为这个子树的权值,为你将1~n放到这个树里

    满足最大权值仅仅有k个的组合数是多少。

    思路:

    我们能够知道以每一个节点为子树。且根节点权值最大的概率是多少,不是的概率是多少。

    那么事实上问题就变成了 我们在n个物品里面,每一个物品拿的概率是pi不拿的概率是1-pi

    问你拿k个物品的概率是多少

    然后最后乘n!就好了。中间计算运用逆元。

    代码:

    #include"cstdlib"
    #include"cstring"
    #include"cmath"
    #include"cstdio"
    #include"queue"
    #include"algorithm"
    #include"iostream"
    #include"stack"
    using namespace std;
    #define ll __int64
    #define N 123456
    vector<int>edge[2234];
    ll sum[1234],dp[1234][1234];
    ll in[1234],mod=1000000007LL;
    ll power(ll a,ll b)
    {
        ll ans=1;
        while(b)
        {
            if(b&1) ans=(ans*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans;
    }
    void dfs(int x,int f)
    {
        int ans=1,lit=edge[x].size();
        for(int i=0; i<lit; i++)
        {
            int v=edge[x][i];
            if(v==f) continue;
            dfs(v,x);
            ans+=sum[v];
        }
        sum[x]=ans;
        return ;
    }
    int main()
    {
        int t,cas=1;
        cin>>t;
        for(int i=1; i<=1234; i++) in[i]=power(i,mod-2); //预处理逆元
        while(t--)
        {
            int n,k;
            scanf("%d%d",&n,&k);
            for(int i=1; i<=n; i++) edge[i].clear();
            for(int i=1; i<n; i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                edge[x].push_back(y);
                edge[y].push_back(x);
            }
            memset(sum,0,sizeof(sum));
            dfs(1,1);
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            for(int i=1; i<=n; i++)
            {
                for(int j=0; j<=k; j++)
                {
                    if(j>0) dp[i][j]=(dp[i][j]+dp[i-1][j-1]*in[sum[i]])%mod;
                    dp[i][j]=(dp[i][j]+(dp[i-1][j]*(sum[i]-1)%mod)*in[sum[i]]%mod)%mod;
                }
            }
    
            ll ans=1;
            for(int i=1; i<=n; i++) ans=(ans*i)%mod;
            ans*=dp[n][k];
            printf("Case #%d: %I64d
    ",cas++,ans%mod);
        }
        return 0;
    }
    



  • 相关阅读:
    视频会议保险行业解决方案
    如何选择适合企业的音视频解决方案?
    移动视频会议市场
    网络视频通讯服务器和平台发展
    移动互联网化的远程医疗
    智能家居行业的音视频技术
    Ubuntu15.04 安装Android开发环境
    AspNetPager 自定义html
    SqlDataReader对象的NextResult方法读取存储过程多个结果集
    一些原生云APP
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6822276.html
Copyright © 2020-2023  润新知