nowcoder375C 小G砍树 换根DP

状态比较好想,但是有一些细节需要注意一下. 

code:

#include <cstring> 
#include <cstdio> 
#include <algorithm> 
#define N 100007 
#define ll long long 
#define mod 998244353 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
int qpow(int x,int y) 
{
    int tmp=1; 
    for(;y;y>>=1,x=(ll)x*x%mod) 
        if(y&1) tmp=(ll)tmp*x%mod; 
    return tmp; 
} 
int edges,n; 
int f[N],inv[N],fac[N],hd[N],to[N<<1],nex[N<<1],size[N],g[N];         
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;  
}      
int C(int x,int y) 
{   
    return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;  
}
void dfs(int u,int ff) 
{
    size[u]=1,f[u]=1; 
    for(int i=hd[u];i;i=nex[i]) 
    {
        int v=to[i]; 
        if(v==ff) continue;  
        dfs(v,u);       
        f[u]=(ll)f[u]%mod*f[v]%mod*C(size[u]+size[v]-1,size[v])%mod;          
        size[u]+=size[v];   
    }  
} 
void dfs2(int u,int ff) 
{
    if(u==1) g[u]=f[u];    
    for(int i=hd[u];i;i=nex[i]) 
    {
        int v=to[i]; 
        if(v==ff) continue;            
        int remain=(ll)g[u]*qpow(f[v],mod-2)%mod*qpow(C(n-1,size[v]),mod-2)%mod;    
        g[v]=(ll)f[v]*remain%mod*C(n-1,n-size[v])%mod;       
        dfs2(v,u); 
    }    
}
int main() 
{
   // setIO("input"); 
    int i,j;  
    scanf("%d",&n); 
    for(i=1;i<n;++i) 
    {
        int x,y; 
        scanf("%d%d",&x,&y); 
        add(x,y),add(y,x);  
    }     
    fac[0]=inv[0]=1; 
    for(i=1;i<=n;++i) fac[i]=(ll)i*fac[i-1]%mod,inv[i]=qpow(fac[i],mod-2);   
    dfs(1,0);     
    dfs2(1,0); 
    int ans=0;       
    for(i=1;i<=n;++i) (ans+=g[i])%=mod; 
    printf("%d\n",ans); 
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/12160479.html