HDU4625 JZPTREE

Description

给定一棵 (n) 点树,边权为 (1)

对于每个点 (x) ,求出

[sum_{i=1}^n dis(x,i)^k ]

[nle 50000,kle 500 ]

Solution

[n^k =sum_{i=0}^k inom n i imes S(k,i) imes i! ]

所以答案推一步就成了

[sum _ {i=1} ^n sum _ {j=0} ^k inom {dis(x,i)} j imes S(k,j) imes j! ]

[sum_{j=0}^k S(k,j) imes j! sum_{i=1}^n inom {dis(x,i)} j ]

所以我们要求啥?

[sum _ {j=0}^ksum _ {i=1}^n inom {dis(x,i)} j ]

这里组合数很难处理……如果转成距离统计空间会挂掉

这里有个 (trick) :杨辉三角

具体可以被写成:

[f[x][i]=f[t][i]+f[t][i-1] ]

Code

#include<bits/stdc++.h>
using namespace std;
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar();
		return res*f;
	}
	const int N=50010,mod=10007;
	struct node{
		int to,nxt;
	}e[N<<1];
	int head[N],cnt,n,k;
	inline void adde(int u,int v)
	{
		e[++cnt].to=v; e[cnt].nxt=head[u];
		return head[u]=cnt,void();
	}
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int del(int x,int y){return x-y>=0?x-y:x-y+mod;}
	int f[N][510],s[510][510],fac[510];
	inline void dfs1(int x,int fat)
	{
		for(int i=head[x];i;i=e[i].nxt)
		{
			int t=e[i].to; if(t==fat) continue; dfs1(t,x); 
			f[x][0]=add(f[x][0],f[t][0]);
			for(int j=1;j<=k;++j) f[x][j]=add(f[x][j],add(f[t][j],f[t][j-1]));
		} ++f[x][0]; 
		return ;
	}
	inline void dfs2(int x,int fa)
	{
		for(int i=head[x];i;i=e[i].nxt)
		{
			int t=e[i].to; if(t==fa) continue;
			for(int j=k;j>=1;--j)
			{
				int r1=del(f[x][j],add(f[t][j],f[t][j-1]));
				int r2=del(f[x][j-1],add(f[t][j-1],j>=2?f[t][j-2]:0));
				f[t][j]=add(f[t][j],add(r1,r2));
			} 
			f[t][0]=add(f[t][0],del(f[x][0],f[t][0]));
			dfs2(t,x);
		} return ;
	}
	inline void work()
	{
		memset(e,0,sizeof(e)); memset(f,0,sizeof(f)); memset(head,0,sizeof(head)); cnt=0;
		n=read(); k=read();
		for(int i=1,u,v;i<n;++i) u=read(),v=read(),adde(u,v),adde(v,u);
		dfs1(1,0); dfs2(1,0);
		for(int i=1;i<=n;++i)
		{
			int ans=0;
			for(int j=0;j<=k;++j) ans=add(ans,f[i][j]*fac[j]%mod*s[k][j]%mod);
			cout<<ans<<endl;
		} return ;
	}
	signed main()
	{
		s[1][1]=fac[0]=fac[1]=1; for(int i=1;i<=500;++i) s[i][1]=1,fac[i]=fac[i-1]*i%mod;  
		for(int i=2;i<=500;++i)
		{
			for(int j=2;j<=i;++j) s[i][j]=add(s[i-1][j-1],s[i-1][j]*j%mod);
		}
		int T=read(); while(T--) work();
		return 0;
	}
}
signed main(){return yspm::main();}
原文地址:https://www.cnblogs.com/yspm/p/13387603.html