HDU 5378(Leader in Tree Land-利用概率dp)

Leader in Tree Land

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 498    Accepted Submission(s): 208


Problem Description
Tree land has n cities, connected by n1 roads. You can go to any city from any city. In other words, this land is a tree. The city numbered one is the root of this tree.

There are n ministers numbered from 1 to n . You will send them to n cities, one city with one minister.

Since this is a rooted tree, each city is a root of a subtree and there are n subtrees. The leader of a subtree is the minister with maximal number in this subtree. As you can see, one minister can be the leader of several subtrees.

One day all the leaders attend a meet, you find that there are exactly k ministers. You want to know how many ways to send n ministers to each city so that there are k ministers attend the meet.

Give your answer mod 1000000007 .
 

Input
Multiple test cases. In the first line there is an integer T , indicating the number of test cases. For each test case, first line contains two numbers n,k . Next n1 line describe the roads of tree land.

T=10,1n1000,1kn
 

Output
For each test case, output one line. The output format is Case # x : ans , x is the case number,starting from 1 .
 

Sample Input
  
  
2 3 2 1 2 1 3 10 8 2 1 3 2 4 1 5 3 6 1 7 3 8 7 9 7 10 6
 

Sample Output
  
  
Case #1: 4 Case #2: 316512
 

Author
UESTC
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5421  5420  5419  5418  5417 


f[i,j] 表示子树i有j个Leader 的方案数

f[i,j]=f[i-1,j]*p+f[i-1,j-1]*(1-p) (p=1/siz[i])

把概率用逆元算来确保精度,

逆元要预处理



#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define MAXN (1000+10)
#define MAXM (2000+10)
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
ll f[MAXN][MAXN];
int n,K;

int edge[MAXM],Next[MAXM],pre[MAXM],siz=1;
void addedge(int u,int v) {
	edge[++siz]=v;
	Next[siz]=pre[u]; 
	pre[u]=siz;
}
void addedge2(int u,int v) {addedge(u,v); addedge(v,u); }

int sz[MAXN];
void dfs(int x,int fa){
	Forp(x) {
		int v=edge[p];
		if (v==fa) continue;
		dfs(v,x);
		sz[x]+=sz[v];
	}
	sz[x]++;
}

int pow2(int a,int b)
{
	if (b==0) return 1;
	if (b==1) return a;
	int t=pow2(a,b/2);
	t=mul(t,t);
	if (b&1) t=mul(t,a);
	return t;
}
int inv[MAXN];
int main()
{
//	freopen("J.in","r",stdin);


	Rep(i,1001) inv[i]=pow2(i,F-2);

	int T;cin>>T;
	For(kcase,T) {
		scanf("%d%d",&n,&K);
		MEM(f) siz=1; MEM(pre) MEM(Next) MEM(edge) MEM(sz)
		For(i,n-1)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			addedge2(u,v);
		} 
		 		
		dfs(1,0);
		
		
		f[0][0]=1;
		For(i,n)
		{
			Rep(j,1+min(K,i))
				f[i][j]=add(mul(mul(f[i-1][j],sz[i]-1),inv[sz[i]]),(j>0)?mul(f[i-1][j-1],inv[sz[i]] ) : 0 );
		}

		ll ans=f[n][K];
		For(i,n) ans=mul(ans,i); 
		
		printf("Case #%d: %I64d\n",kcase,ans);
		
		
		
	} 
	
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值