hdu 5378 Leader in Tree Land

来源:互联网 发布:知客是什么意思 编辑:程序博客网 时间:2024/04/28 22:33

一道很神奇的题目。
给你一颗树,重新给节点编号,一个子树编号最大的那个节点控制整个子树,求有k个控制节点的方案数。
题解的做法是先去求这个点成为控制点的概率,然后再去背包。
算出的概率×N!就是答案了。
神奇从来没想过可以通过概率来算出方案数,太神奇了。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <stdio.h>#include <queue>#include <map>#include <vector>#include <string>#include <cstring>#include <algorithm>#include <iostream>#include <cstdlib>#include <cctype>#include <set>#include <cmath>using namespace std;typedef long long ll;const int MAXN=1e3+10;const int MOD=1e9+7;vector<int> G[MAXN];ll mod_pow(ll v,ll n){    ll ans=1;    while(n)    {        if(n&1) ans=ans*v%MOD;        v=v*v%MOD;        n>>=1;    }    return ans;}int sz[MAXN];void dfs(int u,int fa){    sz[u]=1;    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(v==fa) continue;        dfs(v,u);        sz[u]+=sz[v];    }}ll dp[MAXN][MAXN];int main(){    //freopen("in","r",stdin);    int t,kcase=0;    cin>>t;    while(t--)    {        int n,k;        cin>>n>>k;        for(int i=1;i<=n;i++) G[i].clear();        for(int i=0;i<n-1;i++)        {            int u,v;            scanf("%d%d",&u,&v);            G[u].push_back(v);            G[v].push_back(u);        }        dfs(1,-1);        printf("Case #%d: ",++kcase);        memset(dp,0,sizeof(dp));        dp[0][0]=1;        for(int i=1;i<=n;i++)        {            ll x=mod_pow(sz[i],MOD-2);          for(int j=0; j<=k;j++)          {              dp[i][j]=dp[i-1][j]*(sz[i]-1)%MOD*x%MOD;              if(j)              dp[i][j]=(dp[i][j]+dp[i-1][j-1]*x)%MOD;          }        }        ll ans=dp[n][k];        for(int i=1;i<=n;i++)          ans=ans*i%MOD;        cout<<ans<<endl;    }    return 0;}
0 0
原创粉丝点击