zoukankan      html  css  js  c++  java
  • Crash的文明世界

    description

    题目链接

    给出一个(n) 个点的树,对于每个点(u)

    [S(u)=sum_{i=1}^ndis(i,u)^k ]

    data range

    (nle 50000,kle 150)

    solution

    先来推式子

    [S(u)=sum_{i=1}^ndis(i,u)^k\ =sum_{i=1}^nsum_{j=0}^kleft{egin{matrix}k\jend{matrix} ight}dis(i,u)^{underline j}\ =sum_{j=0}^kj!left{egin{matrix}k\jend{matrix} ight}sum_{i=1}^ninom {dis(i,u)}{j} ]

    因此只需对每个点(u) 和次数(j) 求出(sum_{i=1}^ninom {dis(i,u)}j) 就可以了

    (f_{u,j}=sum_{i=1}^ninom {dis(i,u)}j) ,(up_{u,j}=sum_{i otin u}inom {dis(i,u)}j) ,(down_{u,j}=sum_{iin u}inom {dis(i,u)}j) 显然(f_{u,j}=up_{u,j}+down_{u,j})

    注意组合数有很好的性质

    [inom nm=inom{n-1}m+inom{n-1}{m-1} ]

    先考虑(down_{u,j}) (简单些)

    [down_{u,j}=sum_{iin u}inom{dis(i,u)}j\ =[j=0]+sum_{iin u}(inom{dis(i,u)-1}{j}+inom{dis(i,u)-1}{j-1})\ =[j=0]+sum_{iin u}(inom{dis(i,v)}{j}+inom{dis(i,v)}{j-1})\ =[j=0]+sum_{iin u}(down_{v,j}+down_{v,j-1}) ]

    再考虑(up_{u,j})

    [up_{u,j}=sum_{i otin u}inom{dis(i,u)}j\ =sum_{i otin fa_u}inom{dis(i,fa_u)+1}{j}+sum_{iin fa_u}inom{dis(i,fa_u)+1}j-sum_{iin u}inom{dis(i,u)+2}j\ =up_{fa_u,j}+up_{fa_u,j-1}+down_{fa_u,j}+down_{fa_u,j-1}-down_{u,j}-2down_{u,j-1}-down_{u,j-2} ]

    注意边界上需要特殊处理

    这类题目只是外面套了个斯特林数的外壳,本质还是(dp) 之类的传统东西

    普通幂的差分十分困难(即便预处理组合数也需要(mathcal O(k))),而斯特林数将普通幂转为下降幂使得其差分变得简单((mathcal O(1)))

    time complexity

    (mathcal O(nk))

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e4+5,K=155,mod=1e4+7;
    int f[N][K],s2[K][K],n,k;
    int tot,fi[N],ne[N<<1],to[N<<1];
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    	for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    	return s*w;
    }
    inline void adde(int x,int y){ne[++tot]=fi[x],fi[x]=tot,to[tot]=y;}
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
    inline void pre()
    {
    	s2[0][0]=1;
    	for(int i=1;i<=k;++i)
    		for(int j=1;j<=k;++j)
    			s2[i][j]=add(s2[i-1][j-1],s2[i-1][j]*j%mod);
    }
    int down[N][K],up[N][K];
    void dfs1(int u,int f)
    {
    	down[u][0]=1;
    	for(int i=fi[u];i;i=ne[i])
    	{
    		int v=to[i];
    		if(v==f)continue;
    		dfs1(v,u);
    		down[u][0]=add(down[u][0],down[v][0]);
    		for(int j=1;j<=k;++j)
    			down[u][j]=add(down[u][j],add(down[v][j],down[v][j-1]));
    	}
    }
    void dfs2(int u,int f)
    {
    	int now[K];
    	now[0]=add(up[u][0],down[u][0]);
    	for(int j=1;j<=k;++j)
    		now[j]=(up[u][j]+up[u][j-1]+down[u][j]+down[u][j-1])%mod;
    	for(int i=fi[u];i;i=ne[i])
    	{
    		int v=to[i];
    		if(v==f)continue;
    		up[v][0]=dec(now[0],down[v][0]);
    		up[v][1]=dec(now[1],add(down[v][1],add(down[v][0],down[v][0])));
    		for(int j=2;j<=k;++j)
    			up[v][j]=dec(now[j],add(down[v][j],add(2*down[v][j-1]%mod,down[v][j-2])));
    		dfs2(v,u);
    	}
    }
    int main()
    {
    	n=read(),k=read();
    	for(int i=1,u,v;i<n;++i)
    	{
    		u=read(),v=read();
    		adde(u,v),adde(v,u);
    	}
    	pre();dfs1(1,0);dfs2(1,0);
    	for(int i=1;i<=n;++i)
    	{
    		int ans=0,fac=1;
    		for(int j=0;j<=k;++j,fac=fac*j%mod)
    			ans=add(ans,fac*s2[k][j]%mod*add(up[i][j],down[i][j])%mod);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
    NO PAIN NO GAIN
  • 相关阅读:
    如何安装一个高可用K3s集群?
    如何设置一个生产级别的高可用etcd集群
    从架构到部署,全面了解K3s
    这应该是最适合国内用户的K3s HA方案
    在K3s上使用Kong网关插件,开启K3s的无限可能!
    AngularJS 遗留项目的升级改造之路(一)
    Rancher首席架构师解读Fleet:它何以管理百万集群?
    资深首席架构师预测:2021年云计算的8个首要趋势
    简单4步,利用Prometheus Operator实现自定义指标监控
    当年,我的架构师之路差点完蛋,幸亏了它
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/14403519.html
Copyright © 2011-2022 走看看