Problem:
Problem
頂点 $0$ を根とする $N$ 頂点の根付き木と、長さ $N$ の数列 $A$ が与えられます。
与えられる根付き木の $i$ 番目の辺は頂点 $u_i$ と $v_i$ を結んでいます。
$C(i)$ を、頂点 $i$ の子であるような頂点の番号の集合とします。
長さ $N$ の数列 $B_i$ を以下のように定義します。
$i=0$ なら $(B_i)_j=A_j$
$i>0$ なら $\displaystyle (B_i)_j=(B_{i-1})_j + \sum_{k \in C(j)} (B_i)_k$
数列 $B_M$ を求めてください。
ただし、$B_M$ の各項は非常に大きくなることがあるので、$998244353$ で割ったあまりを出力してください。
Input
入力は以下の形式で与えられる。
$N$ $M$
$A_0$ $A_1$ $\ldots$ $A_{N-1}$
$u_0$ $v_0$
$\vdots$
$u_{N-2}$ $v_{N-2}$
Constraints
入力は以下の条件を満たす。
$2 \leq N \leq 2\times 10^5$
$1 \leq M \lt 998244353$
$0 \leq A_i \lt 998244353$
$0 \leq u_i,v_i \leq N-1$
与えられるグラフは木である
入力は全て整数である
Output
$(B_M)_0,(B_M)_1,\ldots ,(B_M)_{N-1}$ を $998244353$ で割ったあまりをこの順に空白で区切って一行に出力する。
Sample Input 1
2 100000000
1 1
0 1
Sample Output 1
100000001 1
Sample Input 2
5 1
1 10 100 1000 10000
0 1
1 2
1 3
0 4
Sample Output 2
11111 1110 100 1000 10000
Sample Input 3
5 998244352
1 10 100 1000 10000
0 1
1 2
1 3
0 4
Sample Output 3
998234344 998243263 100 1000 10000

Submitted solutions:

code_snippet: // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3084

#include<bits/stdc++.h>
using namespace std;

#define call_from_test

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}
//END CUT HERE
#ifndef call_from_test

//INSERT ABOVE HERE
signed ABC127_E(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int h,w,k;
  cin>>h>>w>>k;
  using M = Mint<int>;

  M ans{0};
  for(int d=1;d<h;d++)
    ans+=M(d)*M(h-d)*M(w)*M(w);

  for(int d=1;d<w;d++)
    ans+=M(d)*M(w-d)*M(h)*M(h);

  ans*=M::comb(h*w-2,k-2);
  cout<<ans<<endl;
  return 0;
}
/*
  verified on 2019/06/12
  https://atcoder.jp/contests/abc127/tasks/abc127_e
*/

signed main(){
  //ABC127_E();
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../mod/mint.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
constexpr int bmds(int x){
  const int v[] = {1012924417, 924844033, 998244353,
                   897581057, 645922817};
  return v[x];
}
constexpr int brts(int x){
  const int v[] = {5, 5, 3, 3, 3};
  return v[x];
}

template<int X>
struct NTT{
  static constexpr int md = bmds(X);
  static constexpr int rt = brts(X);
  using M = Mint<int, md>;
  vector< vector<M> > rts,rrts;

  void ensure_base(int n){
    if((int)rts.size()>=n) return;
    rts.resize(n);rrts.resize(n);
    for(int i=1;i<n;i<<=1){
      if(!rts[i].empty()) continue;
      M w=M(rt).pow((md-1)/(i<<1));
      M rw=w.inv();
      rts[i].resize(i);rrts[i].resize(i);
      rts[i][0]=M(1);rrts[i][0]=M(1);
      for(int k=1;k<i;k++){
        rts[i][k]=rts[i][k-1]*w;
        rrts[i][k]=rrts[i][k-1]*rw;
      }
    }
  }

  void ntt(vector<M> &as,bool f){
    int n=as.size();
    assert((n&(n-1))==0);
    ensure_base(n);

    for(int i=0,j=1;j+1<n;j++){
      for(int k=n>>1;k>(i^=k);k>>=1);
      if(i>j) swap(as[i],as[j]);
    }

    for(int i=1;i<n;i<<=1){
      for(int j=0;j<n;j+=i*2){
        for(int k=0;k<i;k++){
          M z=as[i+j+k]*(f?rrts[i][k]:rts[i][k]);
          as[i+j+k]=as[j+k]-z;
          as[j+k]+=z;
        }
      }
    }

    if(f){
      M tmp=M(n).inv();
      for(int i=0;i<n;i++) as[i]*=tmp;
    }
  }

  vector<M> multiply(vector<M> as,vector<M> bs){
    int need=as.size()+bs.size()-1;
    int sz=1;
    while(sz<need) sz<<=1;
    as.resize(sz,M(0));
    bs.resize(sz,M(0));

    ntt(as,0);ntt(bs,0);
    for(int i=0;i<sz;i++) as[i]*=bs[i];
    ntt(as,1);

    as.resize(need);
    return as;
  }

  vector<int> multiply(vector<int> as,vector<int> bs){
    vector<M> am(as.size()),bm(bs.size());
    for(int i=0;i<(int)am.size();i++) am[i]=M(as[i]);
    for(int i=0;i<(int)bm.size();i++) bm[i]=M(bs[i]);
    vector<M> cm=multiply(am,bm);
    vector<int> cs(cm.size());
    for(int i=0;i<(int)cs.size();i++) cs[i]=cm[i].v;
    return cs;
  }
};
template<int X> constexpr int NTT<X>::md;
template<int X> constexpr int NTT<X>::rt;
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
template<typename M_>
class Enumeration{
  using M = M_;
protected:
  static vector<M> fact,finv,invs;
public:
  static void init(int n){
    n=min<decltype(M::mod)>(n,M::mod-1);

    int m=fact.size();
    if(n<m) return;

    fact.resize(n+1,1);
    finv.resize(n+1,1);
    invs.resize(n+1,1);

    if(m==0) m=1;
    for(int i=m;i<=n;i++) fact[i]=fact[i-1]*M(i);
    finv[n]=M(1)/fact[n];
    for(int i=n;i>=m;i--) finv[i-1]=finv[i]*M(i);
    for(int i=m;i<=n;i++) invs[i]=finv[i]*fact[i-1];
  }

  static M Fact(int n){
    init(n);
    return fact[n];
  }
  static M Finv(int n){
    init(n);
    return finv[n];
  }
  static M Invs(int n){
    init(n);
    return invs[n];
  }

  static M C(int n,int k){
    if(n<k||k<0) return M(0);
    init(n);
    return fact[n]*finv[n-k]*finv[k];
  }

  static M P(int n,int k){
    if(n<k||k<0) return M(0);
    init(n);
    return fact[n]*finv[n-k];
  }

  // put n identical balls into k distinct boxes
  static M H(int n,int k){
    if(n<0||k<0) return M(0);
    if(!n&&!k) return M(1);
    init(n+k);
    return C(n+k-1,n);
  }
};
template<typename M>
vector<M> Enumeration<M>::fact=vector<M>();
template<typename M>
vector<M> Enumeration<M>::finv=vector<M>();
template<typename M>
vector<M> Enumeration<M>::invs=vector<M>();
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#undef call_from_test

#endif
// http://beet-aizu.hatenablog.com/entry/2019/09/27/224701
//BEGIN CUT HERE
template<typename M_>
struct FormalPowerSeries : Enumeration<M_> {
  using M = M_;
  using super = Enumeration<M>;
  using super::fact;
  using super::finv;
  using super::invs;

  using Poly = vector<M>;
  using Conv = function<Poly(Poly, Poly)>;
  Conv conv;
  FormalPowerSeries(Conv conv):conv(conv){}

  Poly pre(const Poly &as,int deg){
    return Poly(as.begin(),as.begin()+min((int)as.size(),deg));
  }

  Poly add(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,M(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]+=bs[i];
    return cs;
  }

  Poly sub(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,M(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]-=bs[i];
    return cs;
  }

  Poly mul(Poly as,Poly bs){
    return conv(as,bs);
  }

  Poly mul(Poly as,M k){
    for(auto &a:as) a*=k;
    return as;
  }

  // F(0) must not be 0
  Poly inv(Poly as,int deg);

  // not zero
  Poly div(Poly as,Poly bs);

  // not zero
  Poly mod(Poly as,Poly bs);

  // F(0) must be 1
  Poly sqrt(Poly as,int deg);

  Poly diff(Poly as);
  Poly integral(Poly as);

  // F(0) must be 1
  Poly log(Poly as,int deg);

  // F(0) must be 0
  Poly exp(Poly as,int deg);

  // not zero
  Poly pow(Poly as,long long k,int deg);

  // x <- x + c
  Poly shift(Poly as,M c);
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#include "./base.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename M>
vector<M> FormalPowerSeries<M>::inv(Poly as,int deg){
  assert(as[0]!=M(0));
  Poly rs({M(1)/as[0]});
  for(int i=1;i<deg;i<<=1)
    rs=pre(sub(add(rs,rs),mul(mul(rs,rs),pre(as,i<<1))),i<<1);
  return rs;
}

//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#include "./base.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename M>
vector<M> FormalPowerSeries<M>::integral(Poly as){
  super::init(as.size()+1);
  int n=as.size();
  Poly rs(n+1);
  rs[0]=M(0);
  for(int i=0;i<n;i++) rs[i+1]=as[i]*invs[i+1];
  return rs;
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#include "./base.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename M>
vector<M> FormalPowerSeries<M>::diff(Poly as){
  int n=as.size();
  Poly rs(n-1);
  for(int i=1;i<n;i++) rs[i-1]=as[i]*M(i);
  return rs;
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#include "./base.cpp"
#include "./inv.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename M>
vector<M> FormalPowerSeries<M>::log(Poly as,int deg){
  return pre(integral(mul(diff(as),inv(as,deg))),deg);
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#include "./base.cpp"
#include "./inv.cpp"
#include "./log.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename M>
vector<M> FormalPowerSeries<M>::exp(Poly as,int deg){
  Poly fs({M(1)});
  as[0]+=M(1);
  for(int i=1;i<deg;i<<=1)
    fs=pre(mul(fs,sub(pre(as,i<<1),log(fs,i<<1))),i<<1);
  return fs;
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#include "./base.cpp"
#include "./inv.cpp"
#include "./log.cpp"
#include "./exp.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename M>
vector<M> FormalPowerSeries<M>::pow(Poly as,long long k,int deg){
  if(as==Poly(as.size(),M(0))) return Poly(deg,M(0));

  int cnt=0;
  while(as[cnt]==M(0)) cnt++;
  if(cnt*k>=deg) return Poly(deg,M(0));
  as.erase(as.begin(),as.begin()+cnt);
  deg-=cnt*k;

  M c=as[0];
  Poly zs(cnt*k,M(0));
  Poly rs=mul(exp(mul(log(mul(as,c.inv()),deg),M(k)),deg),c.pow(k));
  zs.insert(zs.end(),rs.begin(),rs.end());
  return pre(zs,deg+cnt*k);
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
struct Centroid{
  vector<int> sz,dead;
  vector< vector<int> > G;
  Centroid(){}
  Centroid(int n):sz(n,1),dead(n,0),G(n){}

  void add_edge(int u,int v){
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  int dfs(int v,int p){
    sz[v]=1;
    for(int u:G[v])
      if(u!=p and !dead[u]) sz[v]+=dfs(u,v);
    return sz[v];
  }

  void find(int v,int p,int tmp,vector<int> &cs) {
    int ok=1;
    for (int u:G[v]){
      if(u==p or dead[u]) continue;
      find(u,v,tmp,cs);
      ok&=(sz[u]<=tmp/2);
    }
    ok&=(tmp-sz[v]<=tmp/2);
    if(ok) cs.emplace_back(v);
  }

  vector<int> build(int r) {
    int tmp=dfs(r,-1);
    vector<int> cs;
    find(r,-1,tmp,cs);
    return cs;
  }

  const vector<int>& operator[](int k)const{return G[k];}
  void disable(int v){dead[v]=1;}
  void  enable(int v){dead[v]=0;}
  int alive(int v){return !dead[v];}
};
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  NTT<2> ntt;
  using M = decltype(ntt)::M;
  auto conv=[&](auto as,auto bs){return ntt.multiply(as,bs);};
  FormalPowerSeries<M> FPS(conv);
  using Poly = decltype(FPS)::Poly;

  int n,m;
  cin>>n>>m;

  Poly as(n);
  for(int i=0;i<n;i++) cin>>as[i].v;

  Centroid G(n+1);
  G.add_edge(n,0);
  for(int i=1;i<n;i++){
    int u,v;
    cin>>u>>v;
    G.add_edge(u,v);
  }

  vector<int> par(n+1,-1);
  {
    queue<int> que;
    que.emplace(n);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int u:G.G[v]){
        if(u==par[v]) continue;
        par[u]=v;
        que.emplace(u);
      }
    }
  }

  vector<int> dead(n+1,0);
  auto disable=[&](int k){
    dead[k]=1;
    G.disable(k);
  };
  disable(n);

  const int deg = 1<<18;
  Poly ps(n,M(1));
  ps=FPS.pow(ps,m,deg);

  queue<int> que;
  que.emplace(G.build(0)[0]);

  Poly ans(n);
  while(!que.empty()){
    int r=que.front();que.pop();

    Poly qs;
    MFP([&](auto dfs,int v,int p,int h)->void{
      while(!(h<(int)qs.size())) qs.emplace_back(0);
      qs[h]+=as[v];
      for(int u:G.G[v]){
        if(u==p) continue;
        if(dead[u]) continue;
        dfs(u,v,h+1);
      }
    })(r,par[r],0);
    reverse(qs.begin(),qs.end());

    vector<int> bs;
    int p=r;
    while(~p&&!dead[p]){
      bs.emplace_back(p);
      p=par[p];
    }

    int len=qs.size()-1;
    qs.resize(len+bs.size(),M(0));
    auto rs=FPS.mul(FPS.pre(ps,qs.size()),qs);

    for(int i=0;i<(int)bs.size();i++) ans[bs[i]]+=rs[len+i];

    disable(r);
    for(int u:G.G[r])
      if(!dead[u]) que.emplace(G.build(u)[0]);
  }

  for(int i=0;i<n;i++){
    if(i) cout<<" ";
    cout<<ans[i];
  }
  cout<<endl;
  return 0;
}
accuracy: 1
time_ms: 1180
memory_kb: 71744
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, m, n) for(int(i) = (int)(m); i < (int)(n); ++i)
#define rep2(i, m, n) for(int(i) = (int)(n)-1; i >= (int)(m); --i)
#define REP(i, n) rep(i, 0, n)
#define REP2(i, n) rep2(i, 0, n)
#define all(hoge) (hoge).begin(), (hoge).end()
#define en '\n'
using ll = long long;
using ull = unsigned long long;
template <class T>
using vec = vector<T>;
template <class T>
using vvec = vector<vec<T>>;
typedef pair<ll, ll> P;
using tp = tuple<ll, ll, ll>;
constexpr long long INF = 1LL << 60;
constexpr int INF_INT = 1 << 25;
//constexpr long long MOD = (ll)1e9 + 7;
constexpr long long MOD = 998244353LL;
using ld = long double;
static const ld pi = 3.141592653589793L;
typedef vector<ll> Array;
typedef vector<Array> Matrix;

template <class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

//グラフ関連
struct Edge {
    ll to, cap, rev;
    Edge(ll _to, ll _cap, ll _rev) {
        to = _to;
        cap = _cap;
        rev = _rev;
    }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

void add_edge(Graph &G, ll from, ll to, ll cap, bool revFlag, ll revCap) {
    G[from].push_back(Edge(to, cap, (ll)G[to].size()));
    if(revFlag)
        G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));
}

template <int mod>
struct NumberTheoreticTransform {

    vector<int> rev, rts;
    int base, max_base, root;

    NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
        assert(mod >= 3 && mod % 2 == 1);
        auto tmp = mod - 1;
        max_base = 0;
        while(tmp % 2 == 0)
            tmp >>= 1, max_base++;
        root = 2;
        while(mod_pow(root, (mod - 1) >> 1) == 1)
            ++root;
        assert(mod_pow(root, mod - 1) == 1);
        root = mod_pow(root, (mod - 1) >> max_base);
    }

    inline int mod_pow(int x, int n) {
        int ret = 1;
        while(n > 0) {
            if(n & 1)
                ret = mul(ret, x);
            x = mul(x, x);
            n >>= 1;
        }
        return ret;
    }

    inline int inverse(int x) {
        return mod_pow(x, mod - 2);
    }

    inline unsigned add(unsigned x, unsigned y) {
        x += y;
        if(x >= mod)
            x -= mod;
        return x;
    }

    inline unsigned mul(unsigned a, unsigned b) {
        return 1ull * a * b % (unsigned long long)mod;
    }

    void ensure_base(int nbase) {
        if(nbase <= base)
            return;
        rev.resize(1 << nbase);
        rts.resize(1 << nbase);
        for(int i = 0; i < (1 << nbase); i++) {
            rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
        }
        //cout << max_base << endl;
        assert(nbase <= max_base);
        while(base < nbase) {
            int z = mod_pow(root, 1 << (max_base - 1 - base));
            for(int i = 1 << (base - 1); i < (1 << base); i++) {
                rts[i << 1] = rts[i];
                rts[(i << 1) + 1] = mul(rts[i], z);
            }
            ++base;
        }
    }

    void ntt(vector<int> &a) {
        const int n = (int)a.size();
        assert((n & (n - 1)) == 0);
        int zeros = __builtin_ctz(n);
        ensure_base(zeros);
        int shift = base - zeros;
        for(int i = 0; i < n; i++) {
            if(i < (rev[i] >> shift)) {
                swap(a[i], a[rev[i] >> shift]);
            }
        }
        for(int k = 1; k < n; k <<= 1) {
            for(int i = 0; i < n; i += 2 * k) {
                for(int j = 0; j < k; j++) {
                    int z = mul(a[i + j + k], rts[j + k]);
                    a[i + j + k] = add(a[i + j], mod - z);
                    a[i + j] = add(a[i + j], z);
                }
            }
        }
    }

    vector<int> multiply(vector<int> a, vector<int> b) {
        int need = a.size() + b.size() - 1;
        int nbase = 1;
        while((1 << nbase) < need)
            nbase++;
        ensure_base(nbase);
        int sz = 1 << nbase;
        a.resize(sz, 0);
        b.resize(sz, 0);
        ntt(a);
        ntt(b);
        int inv_sz = inverse(sz);
        for(int i = 0; i < sz; i++) {
            a[i] = mul(a[i], mul(b[i], inv_sz));
        }
        reverse(a.begin() + 1, a.end());
        ntt(a);
        a.resize(need);
        return a;
    }
};

template <int mod>
struct ModInt {
    int x;

    ModInt() : x(0) {}

    ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    ModInt &operator+=(const ModInt &p) {
        if((x += p.x) >= mod)
            x -= mod;
        return *this;
    }

    ModInt &operator-=(const ModInt &p) {
        if((x += mod - p.x) >= mod)
            x -= mod;
        return *this;
    }

    ModInt &operator*=(const ModInt &p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }

    ModInt &operator/=(const ModInt &p) {
        *this *= p.inverse();
        return *this;
    }

    ModInt operator-() const { return ModInt(-x); }

    ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

    ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

    ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

    ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

    bool operator==(const ModInt &p) const { return x == p.x; }

    bool operator!=(const ModInt &p) const { return x != p.x; }

    ModInt inverse() const {
        int a = x, b = mod, u = 1, v = 0, t;
        while(b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return ModInt(u);
    }

    ModInt pow(int64_t n) const {
        ModInt ret(1), mul(x);
        while(n > 0) {
            if(n & 1)
                ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend ostream &operator<<(ostream &os, const ModInt &p) {
        return os << p.x;
    }

    friend istream &operator>>(istream &is, ModInt &a) {
        int64_t t;
        is >> t;
        a = ModInt<mod>(t);
        return (is);
    }

    static int get_mod() { return mod; }
};

using mint = ModInt<MOD>;

// 二項係数ライブラリ
template <class T>
struct Combination {
    vector<T> fact_, inv_, finv_;
    constexpr Combination() {}
    constexpr Combination(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n + 1);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].get_mod();
        for(int i = 2; i < n; i++) {
            fact_[i] = fact_[i - 1] * i;
            inv_[i] = -inv_[MOD % i] * (MOD / i);
            finv_[i] = finv_[i - 1] * inv_[i];
        }
    }
    constexpr T nPr(int n, int k) const noexcept {
        if(n < k || n < 0 || k < 0)
            return 0;
        return fact_[n] * finv_[n - k];
    }
    constexpr T nCr(int n, int k) const noexcept {
        if(n < k || n < 0 || k < 0)
            return 0;
        return fact_[n] * finv_[k] * finv_[n - k];
    }
    constexpr T nHr(int n, int k) const noexcept {
        if(n < k || n < 0 || k < 0)
            return 0;
        return nCr(n + k - 1, k);
    }
    constexpr T fact(int n) const noexcept {
        if(n < 0)
            return 0;
        return fact_[n]; //n!
    }
    constexpr T inv(int n) const noexcept {
        if(n < 0)
            return 0;
        return inv_[n]; //1/n
    }
    constexpr T finv(int n) const noexcept {
        if(n < 0)
            return 0;
        return finv_[n]; //1/n!
    }
};

void solve() {
    ll n, m;
    cin >> n >> m;
    vec<int> a(n);
    REP(i, n) {
        cin >> a[i];
    }

    Graph g(n);
    REP(i, n - 1) {
        int u, v;
        cin >> u >> v;
        add_edge(g, u, v, 1, true, 1);
    }

    vec<int> cc(n + 1);

    mint con = 1;
    REP(i, n + 1) {
        cc[i] = con.x;
        con *= m + i;
        con /= (i + 1);
    }

    vec<int> ans(n, 0);
    NumberTheoreticTransform<MOD> ntt;

    auto dfs = [&](auto &&self, int v, int p) -> vvec<int> {
        if((v != 0 and g[v].size() <= 2) or g[v].size() <= 1) {
            //分岐がないとき
            vvec<int> ret(2);

            for(auto e : g[v]) {
                if(e.to == p)
                    continue;
                ret = self(self, e.to, v);
            }

            ret[0].push_back(v);
            ret[1].push_back(a[v]);
            return ret;
        }

        vvec<int> ret(2);
        ret[0].push_back(v);

        for(auto e : g[v]) {
            if(e.to == p)
                continue;
            auto ret2 = self(self, e.to, v);
            vec<int> tmp = ntt.multiply(cc, ret2[1]); //ここまでを計算
            ll k = ret2[1].size() - ret2[0].size();
            REP2(i, ret2[0].size()) {
                ans[ret2[0][i]] = tmp[i + k];
            }

            if(ret[1].size() < ret2[1].size())
                swap(ret[1], ret2[1]);
            REP(i, ret2[1].size()) {
                ret[1][ret[1].size() - 1 - i] += ret2[1][ret2[1].size() - 1 - i]; //重みを加算
            }
        }
        ret[1].push_back(a[v]);

        return ret;
    };
    auto ret2 = dfs(dfs, 0, -1);
    vec<int> tmp = ntt.multiply(cc, ret2[1]); //ここまでを計算
    ll k = ret2[1].size() - ret2[0].size();
    REP2(i, ret2[0].size()) {
        ans[ret2[0][i]] = tmp[i + k];
    }

    REP(i, n) {
        cout << ans[i];
        if(i == n - 1)
            cout << en;
        else
            cout << " ";
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    /*
    ll t;
    cin >> t;
    while(t--)*/
    solve();

    return 0;
}
accuracy: 0.10714285714285714
time_ms: 20
memory_kb: 3472
final_rank: 19

code_snippet: // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3084

#include<bits/stdc++.h>
using namespace std;

#define call_from_test

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}
//END CUT HERE
#ifndef call_from_test

//INSERT ABOVE HERE
signed ABC127_E(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int h,w,k;
  cin>>h>>w>>k;
  using M = Mint<int>;

  M ans{0};
  for(int d=1;d<h;d++)
    ans+=M(d)*M(h-d)*M(w)*M(w);

  for(int d=1;d<w;d++)
    ans+=M(d)*M(w-d)*M(h)*M(h);

  ans*=M::comb(h*w-2,k-2);
  cout<<ans<<endl;
  return 0;
}
/*
  verified on 2019/06/12
  https://atcoder.jp/contests/abc127/tasks/abc127_e
*/

signed main(){
  //ABC127_E();
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../mod/mint.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
constexpr int bmds(int x){
  const int v[] = {1012924417, 924844033, 998244353,
                   897581057, 645922817};
  return v[x];
}
constexpr int brts(int x){
  const int v[] = {5, 5, 3, 3, 3};
  return v[x];
}

template<int X>
struct NTT{
  static constexpr int md = bmds(X);
  static constexpr int rt = brts(X);
  using M = Mint<int, md>;
  vector< vector<M> > rts,rrts;

  void ensure_base(int n){
    if((int)rts.size()>=n) return;
    rts.resize(n);rrts.resize(n);
    for(int i=1;i<n;i<<=1){
      if(!rts[i].empty()) continue;
      M w=M(rt).pow((md-1)/(i<<1));
      M rw=w.inv();
      rts[i].resize(i);rrts[i].resize(i);
      rts[i][0]=M(1);rrts[i][0]=M(1);
      for(int k=1;k<i;k++){
        rts[i][k]=rts[i][k-1]*w;
        rrts[i][k]=rrts[i][k-1]*rw;
      }
    }
  }

  void ntt(vector<M> &as,bool f){
    int n=as.size();
    assert((n&(n-1))==0);
    ensure_base(n);

    for(int i=0,j=1;j+1<n;j++){
      for(int k=n>>1;k>(i^=k);k>>=1);
      if(i>j) swap(as[i],as[j]);
    }

    for(int i=1;i<n;i<<=1){
      for(int j=0;j<n;j+=i*2){
        for(int k=0;k<i;k++){
          M z=as[i+j+k]*(f?rrts[i][k]:rts[i][k]);
          as[i+j+k]=as[j+k]-z;
          as[j+k]+=z;
        }
      }
    }

    if(f){
      M tmp=M(n).inv();
      for(int i=0;i<n;i++) as[i]*=tmp;
    }
  }

  vector<M> multiply(vector<M> as,vector<M> bs){
    int need=as.size()+bs.size()-1;
    int sz=1;
    while(sz<need) sz<<=1;
    as.resize(sz,M(0));
    bs.resize(sz,M(0));

    ntt(as,0);ntt(bs,0);
    for(int i=0;i<sz;i++) as[i]*=bs[i];
    ntt(as,1);

    as.resize(need);
    return as;
  }

  vector<int> multiply(vector<int> as,vector<int> bs){
    vector<M> am(as.size()),bm(bs.size());
    for(int i=0;i<(int)am.size();i++) am[i]=M(as[i]);
    for(int i=0;i<(int)bm.size();i++) bm[i]=M(bs[i]);
    vector<M> cm=multiply(am,bm);
    vector<int> cs(cm.size());
    for(int i=0;i<(int)cs.size();i++) cs[i]=cm[i].v;
    return cs;
  }
};
template<int X> constexpr int NTT<X>::md;
template<int X> constexpr int NTT<X>::rt;
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
template<typename M_>
class Enumeration{
  using M = M_;
protected:
  static vector<M> fact,finv,invs;
public:
  static void init(int n){
    n=min<decltype(M::mod)>(n,M::mod-1);

    int m=fact.size();
    if(n<m) return;

    fact.resize(n+1,1);
    finv.resize(n+1,1);
    invs.resize(n+1,1);

    if(m==0) m=1;
    for(int i=m;i<=n;i++) fact[i]=fact[i-1]*M(i);
    finv[n]=M(1)/fact[n];
    for(int i=n;i>=m;i--) finv[i-1]=finv[i]*M(i);
    for(int i=m;i<=n;i++) invs[i]=finv[i]*fact[i-1];
  }

  static M Fact(int n){
    init(n);
    return fact[n];
  }
  static M Finv(int n){
    init(n);
    return finv[n];
  }
  static M Invs(int n){
    init(n);
    return invs[n];
  }

  static M C(int n,int k){
    if(n<k||k<0) return M(0);
    init(n);
    return fact[n]*finv[n-k]*finv[k];
  }

  static M P(int n,int k){
    if(n<k||k<0) return M(0);
    init(n);
    return fact[n]*finv[n-k];
  }

  // put n identical balls into k distinct boxes
  static M H(int n,int k){
    if(n<0||k<0) return M(0);
    if(!n&&!k) return M(1);
    init(n+k);
    return C(n+k-1,n);
  }
};
template<typename M>
vector<M> Enumeration<M>::fact=vector<M>();
template<typename M>
vector<M> Enumeration<M>::finv=vector<M>();
template<typename M>
vector<M> Enumeration<M>::invs=vector<M>();
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../combinatorics/enumeration.cpp"
#undef call_from_test

#endif

/*
 * @see http://beet-aizu.hatenablog.com/entry/2019/09/27/224701
 */
//BEGIN CUT HERE
template<typename M_>
struct FormalPowerSeries : Enumeration<M_> {
  using M = M_;
  using super = Enumeration<M>;
  using super::fact;
  using super::finv;
  using super::invs;

  using Poly = vector<M>;
  using Conv = function<Poly(Poly, Poly)>;
  Conv conv;
  FormalPowerSeries(Conv conv):conv(conv){}

  Poly pre(const Poly &as,int deg){
    return Poly(as.begin(),as.begin()+min((int)as.size(),deg));
  }

  Poly add(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,M(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]+=bs[i];
    return cs;
  }

  Poly sub(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,M(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]-=bs[i];
    return cs;
  }

  Poly mul(Poly as,Poly bs){
    return conv(as,bs);
  }

  Poly mul(Poly as,M k){
    for(auto &a:as) a*=k;
    return as;
  }

  // F(0) must not be 0
  Poly inv(Poly as,int deg){
    assert(as[0]!=M(0));
    Poly rs({M(1)/as[0]});
    for(int i=1;i<deg;i<<=1)
      rs=pre(sub(add(rs,rs),mul(mul(rs,rs),pre(as,i<<1))),i<<1);
    return rs;
  }

  // not zero
  Poly div(Poly as,Poly bs){
    while(as.back()==M(0)) as.pop_back();
    while(bs.back()==M(0)) bs.pop_back();
    if(bs.size()>as.size()) return Poly();
    reverse(as.begin(),as.end());
    reverse(bs.begin(),bs.end());
    int need=as.size()-bs.size()+1;
    Poly ds=pre(mul(as,inv(bs,need)),need);
    reverse(ds.begin(),ds.end());
    return ds;
  }

  Poly mod(Poly as,Poly bs){
    if(as==Poly(as.size(),0)) return Poly({0});
    as=sub(as,mul(div(as,bs),bs));
    if(as==Poly(as.size(),0)) return Poly({0});
    while(as.back()==M(0)) as.pop_back();
    return as;
  }

  // F(0) must be 1
  Poly sqrt(Poly as,int deg){
    assert(as[0]==M(1));
    M inv2=M(1)/M(2);
    Poly ss({M(1)});
    for(int i=1;i<deg;i<<=1){
      ss=pre(add(ss,mul(pre(as,i<<1),inv(ss,i<<1))),i<<1);
      for(M &x:ss) x*=inv2;
    }
    return ss;
  }

  Poly diff(Poly as){
    int n=as.size();
    Poly rs(n-1);
    for(int i=1;i<n;i++) rs[i-1]=as[i]*M(i);
    return rs;
  }

  Poly integral(Poly as){
    super::init(as.size()+1);
    int n=as.size();
    Poly rs(n+1);
    rs[0]=M(0);
    for(int i=0;i<n;i++) rs[i+1]=as[i]*invs[i+1];
    return rs;
  }

  // F(0) must be 1
  Poly log(Poly as,int deg){
    return pre(integral(mul(diff(as),inv(as,deg))),deg);
  }

  // F(0) must be 0
  Poly exp(Poly as,int deg){
    Poly fs({M(1)});
    as[0]+=M(1);
    for(int i=1;i<deg;i<<=1)
      fs=pre(mul(fs,sub(pre(as,i<<1),log(fs,i<<1))),i<<1);
    return fs;
  }

  // not zero
  Poly pow(Poly as,long long k,int deg){
    if(as==Poly(as.size(),M(0))) return Poly(deg,M(0));

    int cnt=0;
    while(as[cnt]==M(0)) cnt++;
    if(cnt*k>=deg) return Poly(deg,M(0));
    as.erase(as.begin(),as.begin()+cnt);
    deg-=cnt*k;

    M c=as[0];
    Poly zs(cnt*k,M(0));
    Poly rs=mul(exp(mul(log(mul(as,c.inv()),deg),M(k)),deg),c.pow(k));
    zs.insert(zs.end(),rs.begin(),rs.end());
    return pre(zs,deg+cnt*k);
  }

  // x -> x + c
  Poly shift(Poly as,M c){
    super::init(as.size()+1);
    int n=as.size();
    for(int i=0;i<n;i++) as[i]*=fact[i];
    reverse(as.begin(),as.end());
    Poly bs(n,M(1));
    for(int i=1;i<n;i++)
      bs[i]=bs[i-1]*c*invs[i];
    as=pre(mul(as,bs),n);
    reverse(as.begin(),as.end());
    for(int i=0;i<n;i++) as[i]*=finv[i];
    return as;
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
struct Centroid{
  vector<int> sz,dead;
  vector< vector<int> > G;
  Centroid(){}
  Centroid(int n):sz(n,1),dead(n,0),G(n){}

  void add_edge(int u,int v){
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  int dfs(int v,int p){
    sz[v]=1;
    for(int u:G[v])
      if(u!=p&&!dead[u]) sz[v]+=dfs(u,v);
    return sz[v];
  }

  void find(int v,int p,int tmp,vector<int> &cs) {
    int ok=1;
    for (int u:G[v]){
      if(u==p||dead[u]) continue;
      find(u,v,tmp,cs);
      ok&=(sz[u]<=tmp/2);
    }
    ok&=(tmp-sz[v]<=tmp/2);
    if(ok) cs.emplace_back(v);
  }

  vector<int> build(int r) {
    int tmp=dfs(r,-1);
    vector<int> cs;
    find(r,-1,tmp,cs);
    return cs;
  }

  const vector<int>& operator[](int k)const{return G[k];}
  void disable(int v){dead[v]=1;}
  void  enable(int v){dead[v]=0;}
  int alive(int v){return !dead[v];}
};
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  NTT<2> ntt;
  using M = decltype(ntt)::M;
  auto conv=[&](auto as,auto bs){return ntt.multiply(as,bs);};
  FormalPowerSeries<M> FPS(conv);
  using Poly = decltype(FPS)::Poly;

  int n,m;
  cin>>n>>m;

  Poly as(n);
  for(int i=0;i<n;i++) cin>>as[i].v;

  Centroid G(n+1);
  G.add_edge(n,0);
  for(int i=1;i<n;i++){
    int u,v;
    cin>>u>>v;
    G.add_edge(u,v);
  }

  vector<int> par(n+1,-1);
  {
    queue<int> que;
    que.emplace(n);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int u:G.G[v]){
        if(u==par[v]) continue;
        par[u]=v;
        que.emplace(u);
      }
    }
  }

  vector<int> dead(n+1,0);
  auto disable=[&](int k){
    dead[k]=1;
    G.disable(k);
  };
  disable(n);

  const int deg = 1<<18;
  Poly ps(n,M(1));
  ps=FPS.exp(FPS.mul(FPS.log(ps,deg),M(m)),deg);

  queue<int> que;
  que.emplace(G.build(0)[0]);

  Poly ans(n);
  while(!que.empty()){
    int r=que.front();que.pop();

    Poly qs;
    MFP([&](auto dfs,int v,int p,int h)->void{
      while(!(h<(int)qs.size())) qs.emplace_back(0);
      qs[h]+=as[v];
      for(int u:G.G[v]){
        if(u==p) continue;
        if(dead[u]) continue;
        dfs(u,v,h+1);
      }
    })(r,par[r],0);
    reverse(qs.begin(),qs.end());

    vector<int> bs;
    int p=r;
    while(~p&&!dead[p]){
      bs.emplace_back(p);
      p=par[p];
    }

    int len=qs.size()-1;
    qs.resize(len+bs.size(),M(0));
    auto rs=FPS.mul(FPS.pre(ps,qs.size()),qs);

    for(int i=0;i<(int)bs.size();i++) ans[bs[i]]+=rs[len+i];

    disable(r);
    for(int u:G.G[r])
      if(!dead[u]) que.emplace(G.build(u)[0]);
  }

  for(int i=0;i<n;i++){
    if(i) cout<<" ";
    cout<<ans[i];
  }
  cout<<endl;
  return 0;
}
accuracy: 1
time_ms: 1160
memory_kb: 71584
final_rank: 12

code_snippet: #pragma region Macros
#pragma GCC optimize("O3")
#pragma GCC target("avx2,avx")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
string YES[2] = {"NO", "YES"};
string Yes[2] = {"No", "Yes"};
string yes[2] = {"no", "yes"};
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return move(res);
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return move(res);
}

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto &e : v) cout << e << " ";
    cout << endl;
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    cout << "(" << p.fi << ", " << p.se << ")";
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
template <class A> string to_string(A v) {
    if(v.empty()) return "{}";
    string ret = "{";
    for(auto &x : v) ret += to_string(x) + ",";
    ret.back() = '}';
    return ret;
}

void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#define endl '\n'
#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
#define debug(x)
#endif
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
// ll rndll(ll n) { return uniform_int_distribution<ll>(0, n - 1)(rng); }

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#pragma endregion

namespace modular {
constexpr ll MOD = 998244353;
const int MAXN = 1100000;
template <ll Modulus> class modint {
    using u64 = ll;

  public:
    u64 a;

    constexpr modint(const u64 x = 0) noexcept : a(((x % Modulus) + Modulus) % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept { return modint(*this) += rhs; }
    constexpr modint operator-(const modint rhs) const noexcept { return modint(*this) -= rhs; }
    constexpr modint operator*(const modint rhs) const noexcept { return modint(*this) *= rhs; }
    template <typename T> constexpr modint operator^(T rhs) const noexcept { return modint(*this) ^= rhs; }
    constexpr modint operator-() const noexcept { return modint() - *this; }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if(a >= Modulus) { a -= Modulus; }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if(a < rhs.a) { a += Modulus; }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr bool operator==(const modint rhs) const noexcept { return a == rhs.a; }
    template <typename T> constexpr modint &operator^=(T n) noexcept {
        modint<Modulus> res = 1;
        modint<Modulus> x = a;
        while(n) {
            if(n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        a = res.a;
        return *this;
    }
};
#define mint modint<MOD>
#define vmint vector<mint>
vmint Inv{0, 1}, Prd{1, 1}, Invprd{1, 1};
mint inv(int n) {
    if(n > MAXN) return mint(n) ^ (MOD - 2);
    if(Inv.size() > n)
        return Inv[n];
    else {
        for(int i = Inv.size(); i <= n; ++i) Inv.emplace_back(Inv[MOD % i] * (-MOD / i));
        return Inv[n];
    }
}
mint inv(mint x) { return inv(x.a); }
mint prd(int n) {
    if(Prd.size() > n)
        return Prd[n];
    else
        for(int i = Prd.size(); i <= n; ++i) Prd.emplace_back(Prd[i - 1] * i);
    return Prd[n];
}
mint invprd(int n) {
    if(Invprd.size() > n)
        return Invprd[n];
    else
        for(int i = Invprd.size(); i <= n; ++i) Invprd.emplace_back(Invprd[i - 1] * inv(i));
    return Invprd[n];
}
mint modpow(ll a, ll n) {
    mint x = a;
    return x ^= n;
}
mint operator/(mint l, mint r) { return l * inv(r); }
mint &operator/=(mint &l, mint r) { return l = l / r; }
mint C(int a, int b) {
    if(a < 0 || b < 0) return 0;
    if(a < b) return 0;
    return prd(a) * invprd(b) * invprd(a - b);
}
mint P(int a, int b) {
    if(a < 0 || b < 0) return 0;
    if(a < b) return 0;
    return prd(a) * invprd(a - b);
}
ostream &operator<<(ostream &os, mint a) {
    os << a.a;
    return os;
}
ostream &operator<<(ostream &os, vmint a) {
    for(auto &e : a) os << e << " ";
    return os;
}
mint operator*(ll x, mint y) { return y * x; }
istream &operator>>(istream &is, mint &a) {
    ll x;
    is >> x;
    a = x;
    return is;
}
mint proot = 3;

void FMT(vmint &f, const bool is_inv = false) {
    const int n = f.size();
    const mint root = is_inv ? inv(proot) : proot;
    vmint g(n);
    for(int b = n >> 1; b > 0; b >>= 1) {
        mint a = root ^ ((MOD - 1) / (n / b)), p = 1;
        for(int i = 0; i < n; i += b << 1) {
            rep(j, b) {
                f[i + j + b] *= p;
                g[(i >> 1) + j] = f[i + j] + f[i + b + j];
                g[(n >> 1) + (i >> 1) + j] = f[i + j] - f[i + b + j];
            }
            p *= a;
        }
        swap(f, g);
    }
    if(is_inv) rep(i, n) f[i] *= inv(n);
}

vmint mul(vmint x, const vmint &y) {
    int n = x.size() + y.size() - 1;
    int s = 1;
    while(s < n) s <<= 1;
    x.resize(s);
    FMT(x);
    vmint z(s);
    rep(i, y.size()) z[i] = y[i];
    FMT(z);
    rep(i, s) x[i] *= z[i];
    FMT(x, true);
    x.resize(n);
    return x;
}

using Poly = vmint;
Poly operator-(Poly f) {
    for(auto &&e : f) e = -e;
    return f;
}
Poly &operator+=(Poly &l, const Poly &r) {
    l.resize(max(l.size(), r.size()));
    rep(i, r.size()) l[i] += r[i];
    return l;
}
Poly operator+(Poly l, const Poly &r) { return l += r; }
Poly &operator-=(Poly &l, const Poly &r) {
    l.resize(max(l.size(), r.size()));
    rep(i, r.size()) l[i] -= r[i];
    return l;
}
Poly operator-(Poly l, const Poly &r) { return l -= r; }
Poly &operator<<=(Poly &f, size_t n) { return f.insert(f.begin(), n, 0), f; }
Poly operator<<(Poly f, size_t n) { return f <<= n; }
Poly &operator>>=(Poly &f, size_t n) { return f.erase(f.begin(), f.begin() + min(f.size(), n)), f; }
Poly operator>>(Poly f, size_t n) { return f >>= n; }
Poly operator*(const Poly &l, const Poly &r) { return mul(l, r); }
Poly &operator*=(Poly &l, const Poly &r) { return l = l * r; }
Poly inv(const Poly &f) {
    Poly g{1 / f[0]};
    while(g.size() < f.size()) {
        Poly x(f.begin(), f.begin() + min(f.size(), g.size() << 1)), y = g;
        x.resize(g.size() << 1), FMT(x);
        y.resize(g.size() << 1), FMT(y);
        rep(i, x.size()) x[i] *= y[i];
        FMT(x, true);
        x >>= g.size();
        x.resize(g.size() << 1), FMT(x);
        rep(i, x.size()) x[i] *= -y[i];
        FMT(x, true);
        g.insert(g.end(), x.begin(), x.begin() + g.size());
    }
    return Poly{begin(g), begin(g) + f.size()};
}
Poly integ(const Poly &f) {
    Poly res(f.size() + 1);
    for(int i = 1; i < (int)res.size(); ++i) res[i] = f[i - 1] / i;
    return res;
}
Poly deriv(const Poly &f) {
    if(f.size() == 0) return Poly();
    Poly res(f.size() - 1);
    rep(i, res.size()) res[i] = f[i + 1] * (i + 1);
    return res;
}
Poly log(const Poly &f) {
    Poly g = integ(inv(f) * deriv(f));
    return Poly{g.begin(), g.begin() + f.size()};
}
Poly exp(const Poly &f) {
    Poly g{1};
    while(g.size() < f.size()) {
        Poly x(f.begin(), f.begin() + min(f.size(), g.size() * 2));
        x[0] += 1;
        g.resize(2 * g.size());
        x -= log(g);
        x *= {g.begin(), g.begin() + g.size() / 2};
        rep2(i, g.size() / 2, min<int>(x.size(), g.size()) - 1) g[i] = x[i];
    }
    return {g.begin(), g.begin() + f.size()};
}

} // namespace modular
using namespace modular;

int main() {
    INT(n, m);
    VEC(int, a, n);
    Graph g(n);
    rep(i, n - 1) {
        INT(u, v);
        g[u].eb(v), g[v].eb(u);
    }
    vi sub(n);
    vmint ans(n);
    vmint binom(n + 1);
    binom[0] = 1;
    rep2(i, 1, n) { binom[i] = binom[i - 1] * ((m - 1) + i) * inv(i); }
    vv(int, v, n);
    vv(mint, dp, n);
    auto dfs = [&](auto &&f, int x, int p) -> void {
        for(auto e : g[x]) {
            if(e != p) {
                f(f, e, x);
                if(si(v[e]) > si(v[x])) swap(v[e], v[x]), swap(dp[e], dp[x]);
                int a = si(v[x]), b = si(v[e]);
                if(!b) continue;
                vmint G(b + 1);
                rep(i, b + 1) G[i] = binom[i];
                auto F = dp[e] * G;
                rep(i, b) ans[v[e][i]] += F[i];
                int d = a - b;
                rep(i, b) ans[v[x][i + d]] -= F[i];
                rep(i, b) dp[x][i + d] += dp[e][i];
                // cout << ans << endl;
            }
        }
        v[x].eb(x), dp[x].eb(a[x]);
    };
    dfs(dfs, 0, -1);
    int k = si(v[0]);
    vmint G(k);
    rep(i, k) G[i] = binom[i];
    auto F = dp[0] * G;
    rep(i, k) ans[v[0][i]] += F[i];
    rep(i, n) {
        if(i) cout << " ";
        cout << ans[i];
    }
    cout << endl;
}
accuracy: 1
time_ms: 170
memory_kb: 50172
final_rank: 5

code_snippet: #include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#define llint long long
#define inf 1e18
#define rep(x, s, t) for(llint (x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for(llint (x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))
const llint mod = 998244353;

using namespace std;
typedef pair<llint, llint> P;

llint modpow(llint a, llint n, llint mod)
{
	if(n == 0) return 1;
	if(n % 2){
		return ((a%mod) * (modpow(a, n-1, mod)%mod)) % mod;
	}
	else{
		return modpow((a*a)%mod, n/2, mod) % mod;
	}
}

int rev(int x, int n)
{
	int ret = 0;
	for(int i = 0; i < n; i++){
		ret <<= 1;
		ret |= (x>>i) & 1;
	}
	return ret;
}

//f[]とF[]は異なる実体を持たなければならない。rootには1の原始2^n乗根を渡す
void DFT(llint f[], llint F[], int n, llint mod, llint root)
{
	int N = 1<<n;
	for(int i = 0; i < N; i++) F[rev(i, n)] = f[i];
	
	llint a, b, x, z;
	for(int i = 1; i <= n; i++){
		int l = 1<<i;
		z = modpow(root, 1<<(n-i), mod);
		for(int j = 0; j < N/l; j++){
			x = 1;
			for(int k = 0; k < l/2; k++){
				a = F[j*l+k], b = F[j*l+k+l/2];
				F[j*l+k] = a + x * b % mod;
				F[j*l+k+l/2] = a - x * b % mod + mod;
				if(F[j*l+k] >= mod) F[j*l+k] -= mod;
				if(F[j*l+k+l/2] >= mod) F[j*l+k+l/2] -= mod;
				x *= z, x %= mod;
			}
		}
	}
}

//f[]とF[]は異なる実体を持たなければならない。rootには1の原始2^n乗根を渡す
void IDFT(llint F[], llint f[], int n, llint mod, llint root)
{
	int N = 1<<n;
	for(int i = 0; i < N; i++) f[rev(i, n)] = F[i];
	root = modpow(root, mod-2, mod);
	
	llint a, b, x, z;
	for(int i = 1; i <= n; i++){
		int l = 1<<i;
		z = modpow(root, 1<<(n-i), mod);
		for(int j = 0; j < N/l; j++){
			x = 1;
			for(int k = 0; k < l/2; k++){
				a = f[j*l+k], b = f[j*l+k+l/2];
				f[j*l+k] = a + x * b % mod;
				f[j*l+k+l/2] = a - x * b % mod + mod;
				if(f[j*l+k] >= mod) f[j*l+k] -= mod;
				if(f[j*l+k+l/2] >= mod) f[j*l+k+l/2] -= mod;
				x *= z, x %= mod;
			}
		}
	}
	llint Ninv = modpow(N, mod-2, mod);
	for(int i = 0; i < N; i++) f[i] *= Ninv, f[i] %= mod;
}

llint n, m;
llint a[200005];
set<llint> G[200005];
llint parent[200005], depth[200005];
priority_queue<P, vector<P>, greater<P> > Q;
llint comb[200005];
llint ans[200005], sub[200005];

llint root;
vector<llint> vec, vec2;

void dfs(int v, int p, int d)
{
	parent[v] = p, depth[v] = d;
	for(auto it = G[v].begin(); it != G[v].end(); it++){
		if(*it == p) continue;
		dfs(*it, v, d+1);
	}
}

llint f[1<<19], f2[1<<19], F[1<<19], F2[1<<19];
void calc()
{
	llint l = vec.size(), n = 1;
	for(llint t=l; t; t/=2) n++;
	
	llint N = 1<<n;
	for(int i = 0; i < N; i++) f[i] = f2[i] = F[i] = F2[i] = 0;
	for(int i = 0; i < l; i++) f[i] = a[vec[i]], f2[i] = comb[i];
	
	llint r = modpow(root, 1<<(23-n), mod);
	DFT(f, F, n, mod, r);
	DFT(f2, F2, n, mod, r);
	for(int i = 0; i < N; i++) F[i] *= F2[i], F[i] %= mod;
	IDFT(F, f, n, mod, r);
	
	for(int i = 0; i < vec.size(); i++) (ans[vec[i]] += f[i]) %= mod;
}

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> m;
	for(int i = 0; i < n; i++) cin >> a[i];
	llint u, v;
	for(int i = 1; i <= n-1; i++){
		cin >> u >> v;
		G[u].insert(v);
		G[v].insert(u);
	}
	dfs(0, -1, 0);
	
	
	for(int i = 0; i < n; i++){
		G[i].erase(parent[i]);
		if(G[i].size() == 0) Q.push(P(depth[i], i));
	}
	
	comb[0] = 1;
	for(int i = 1; i <= n; i++){
		comb[i] = comb[i-1] * (m+i-1) % mod;
		comb[i] *= modpow(i, mod-2, mod), comb[i] %= mod;
	}
	root = modpow(3, 119, mod);
	
	while(Q.size()){
		llint v = Q.top().second;
		Q.pop();
		
		llint p;
		vec.clear(), vec2.clear();
		while(1){
			vec.push_back(v);
			p = parent[v];
			if(p == -1 || G[p].size() >= 2){
				G[p].erase(v);
				break;
			}
			v = p;
		}
		if(p != -1){
			for(int i = 0; i < vec.size(); i++){
				p = *G[p].begin();
				vec2.push_back(p);
			}
		}
		reverse(vec2.begin(), vec2.end());
		
		calc();
		
		for(int i = 0; i < vec2.size(); i++){
			(a[vec2[i]] += a[vec[i]]) %= mod;
			(sub[vec2[i]] += ans[vec[i]]) %= mod;
		}
	}
	
	for(int i = 0; i < n; i++) ans[i] += mod - sub[i], ans[i] %= mod;
	for(int i = 0; i < n; i++){
		cout << ans[i];
		if(i < n-1) cout << " ";
	}
	cout << endl;
	
	return 0;
}
accuracy: 1
time_ms: 1090
memory_kb: 45728
final_rank: 9

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 1 << 21;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

ll mod_inverse(ll a) {
	return mod_pow(a, mod - 2);
}
ll root[24], invroot[24];
void init() {
	rep(i, 24) {
		int n = (1 << i);
		root[i] = mod_pow(3, (mod - 1) / n);
		invroot[i] = mod_inverse(root[i]);
	}
}
typedef vector <ll> poly;
poly dft(poly f, bool inverse = false) {
	int n = f.size(); int i, j, k;
	//bit左右反転
	for (i = 0, j = 1; j < n - 1; j++) {
		for (k = n >> 1; k > (i ^= k); k >>= 1);
		if (i > j)swap(f[i], f[j]);
	}
	for (int j = 1; (1 << j) <= n; j++) {
		int m = 1 << j;
		ll zeta = root[j];
		if (inverse)zeta = invroot[j];
		for (i = 0; i < n; i += m) {
			ll powzeta = 1;
			for (k = i; k < i + m / 2; k++) {
				ll t1 = f[k], t2 = powzeta * f[k + m / 2] % mod;
				f[k] = t1 + t2; while (f[k] >= mod)f[k] -= mod;
				f[k + m / 2] = t1 - t2 + mod; while (f[k + m / 2] >= mod)f[k + m / 2] -= mod;
				(powzeta *= zeta) %= mod;
			}
		}
	}
	if (inverse) {
		ll rv = mod_inverse(n);
		for (i = 0; i < n; i++) {
			(f[i] *= rv) %= mod;
		}
	}
	return f;
}
poly multiply(poly g, poly h) {
	int n = 1;
	int pi = 0, qi = 0;
	rep(i, g.size())if (g[i])pi = i;
	rep(i, h.size())if (h[i])qi = i;
	int sz = pi + qi + 2;
	while (n < sz)n *= 2;
	g.resize(n); h.resize(n);
	/*while (g.size() < n) {
	g.push_back(0);
	}
	while (h.size() < n) {
	h.push_back(0);
	}*/
	poly gg = dft(g);
	poly hh = dft(h);
	poly ff; ff.resize(n);
	rep(i, n) {
		ff[i] = gg[i] * hh[i] % mod;
	}
	return dft(ff, true);
}
void solve() {
	int n; cin >> n; int m; cin >> m; m--;
	vector<ll> a(n);
	rep(i, n)cin >> a[i];
	vector<modint> c(n + 1);
	c[0] = 1;
	rep1(i, n) {
		c[i] = c[i - 1] * (modint)(m + i) / (modint)i;
	}
	vector<vector<int>> G(n);
	rep(i, n - 1) {
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	vector<int> nex(n);
	vector<int> depth(n);
	vector<int> par(n);
	function<int(int, int)>init_dfs = [&](int id, int fr)->int {
		par[id] = fr;
		nex[id] = id;
		int res = depth[id];
		for (int to : G[id])if (to != fr) {
			depth[to] = depth[id] + 1;
			int x = init_dfs(to, id);
			if (res < x) {
				res = x;
				nex[id] = to;
			}
		}
		return res;
	}; init_dfs(0, -1);
	vector<modint> ans(n);
	function<vector<modint>(int)> dfs = [&](int root)->vector<modint> {
		int cur = root;
		vector<int> ids;
		ids.push_back(cur);
		while (nex[cur] != cur) {
			cur = nex[cur]; ids.push_back(cur);
		}

		cur = root;
		int tmp = 0;
		while (nex[cur] != cur) {
			tmp++;
			for (int to : G[cur])if (to != nex[cur] && to != par[cur]) {
				vector<modint> np = dfs(to);
				rep(j, np.size()) {
					ans[ids[j + tmp]] -= np[j];
				}
			}
			cur = nex[cur];
		}
		int dep = depth[cur] - depth[root];
		poly p(dep + 1);
		function<void(int, int)> subdfs = [&](int id, int fr) {
			int d = depth[id] - depth[root];
			p[d] += a[id];
			for (int to : G[id])if (to != fr) {
				subdfs(to, id);
			}
		}; subdfs(root, par[root]);
		poly coef;
		for (int i = dep; i >= 0; i--)coef.push_back(c[i]);
		poly r = multiply(p, coef);
		vector<modint> res(dep + 1);
		rep(i, dep + 1) {
			res[i] = r[i + dep];
			ans[ids[i]] += res[i];
		}
		return res;
	};
	dfs(0);
	rep(i, n) {
		if (i > 0)cout << " ";
		cout << ans[i];
	}
	cout << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(15);
	init_f();
	init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.9642857142857143
time_ms: 330
memory_kb: 71032
final_rank: 18

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 1 << 21;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

ll mod_inverse(ll a) {
	return mod_pow(a, mod - 2);
}
ll root[24], invroot[24];
void init() {
	rep(i, 24) {
		int n = (1 << i);
		root[i] = mod_pow(3, (mod - 1) / n);
		invroot[i] = mod_inverse(root[i]);
	}
}
typedef vector <ll> poly;
poly dft(poly f, bool inverse = false) {
	int n = f.size(); int i, j, k;
	//bit左右反転
	for (i = 0, j = 1; j < n - 1; j++) {
		for (k = n >> 1; k > (i ^= k); k >>= 1);
		if (i > j)swap(f[i], f[j]);
	}
	for (int j = 1; (1 << j) <= n; j++) {
		int m = 1 << j;
		ll zeta = root[j];
		if (inverse)zeta = invroot[j];
		for (i = 0; i < n; i += m) {
			ll powzeta = 1;
			for (k = i; k < i + m / 2; k++) {
				ll t1 = f[k], t2 = powzeta * f[k + m / 2] % mod;
				f[k] = t1 + t2; while (f[k] >= mod)f[k] -= mod;
				f[k + m / 2] = t1 - t2 + mod; while (f[k + m / 2] >= mod)f[k + m / 2] -= mod;
				(powzeta *= zeta) %= mod;
			}
		}
	}
	if (inverse) {
		ll rv = mod_inverse(n);
		for (i = 0; i < n; i++) {
			(f[i] *= rv) %= mod;
		}
	}
	return f;
}
poly multiply(poly g, poly h) {
	int n = 1;
	int pi = 0, qi = 0;
	rep(i, g.size())if (g[i])pi = i;
	rep(i, h.size())if (h[i])qi = i;
	int sz = pi + qi + 2;
	while (n < sz)n *= 2;
	g.resize(n); h.resize(n);
	/*while (g.size() < n) {
	g.push_back(0);
	}
	while (h.size() < n) {
	h.push_back(0);
	}*/
	poly gg = dft(g);
	poly hh = dft(h);
	poly ff; ff.resize(n);
	rep(i, n) {
		ff[i] = gg[i] * hh[i] % mod;
	}
	return dft(ff, true);
}
void solve() {
	int n; cin >> n; int m; cin >> m; m--;
	vector<ll> a(n);
	rep(i, n)cin >> a[i];
	vector<modint> c(n + 1);
	c[0] = 1;
	rep1(i, n) {
		c[i] = c[i - 1] * (modint)(m + i) / (modint)i;
	}
	vector<vector<int>> G(n);
	rep(i, n - 1) {
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	vector<int> nex(n);
	vector<int> depth(n);
	vector<int> par(n);
	function<int(int, int)>init_dfs = [&](int id, int fr)->int {
		par[id] = fr;
		nex[id] = id;
		int res = depth[id];
		for (int to : G[id])if (to != fr) {
			depth[to] = depth[id] + 1;
			int x = init_dfs(to, id);
			if (res < x) {
				res = x;
				nex[id] = to;
			}
		}
		return res;
	}; init_dfs(0, -1);
	vector<modint> ans(n);
	function<vector<modint>(int)> dfs = [&](int root)->vector<modint> {
		int cur = root;
		vector<int> ids;
		ids.push_back(cur);
		while (nex[cur] != cur) {
			cur = nex[cur]; ids.push_back(cur);
		}

		cur = root;
		int tmp = 0;
		while (nex[cur] != cur) {
			tmp++;
			for (int to : G[cur])if (to != nex[cur] && to != par[cur]) {
				vector<modint> nex = dfs(to);
				rep(j, nex.size()) {
					ans[ids[j + tmp]] -= nex[j];
				}
			}
			cur = nex[cur];
		}
		int dep = depth[cur] - depth[root];
		poly p(dep + 1);
		function<void(int, int)> subdfs = [&](int id, int fr) {
			int d = depth[id] - depth[root];
			p[d] += a[id];
			for (int to : G[id])if (to != fr) {
				subdfs(to, id);
			}
		}; subdfs(root, par[root]);
		poly coef;
		for (int i = dep; i >= 0; i--)coef.push_back(c[i]);
		poly r = multiply(p, coef);
		vector<modint> res(dep + 1);
		rep(i, dep + 1) {
			res[i] = r[i + dep];
			ans[ids[i]] += res[i];
		}
		return res;
	};
	dfs(0);
	rep(i, n) {
		if (i > 0)cout << " ";
		cout << ans[i];
	}
	cout << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(15);
	init_f();
	init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.9642857142857143
time_ms: 330
memory_kb: 71008
final_rank: 17

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 1 << 21;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

int get_premitive_root() {
	int primitive_root = 0;
	if (!primitive_root) {
		primitive_root = [&]() {
			set<int> fac;
			int v = mod - 1;
			for (ll i = 2; i * i <= v; i++) while (v % i == 0) fac.insert(i), v /= i;
			if (v > 1) fac.insert(v);
			for (int g = 1; g < mod; g++) {
				bool ok = true;
				for (auto i : fac) if (mod_pow(g, (mod - 1) / i) == 1) { ok = false; break; }
				if (ok) return g;
			}
			return -1;
		}();
	}
	return primitive_root;
}
const int proot = get_premitive_root();

typedef vector <modint> poly;
void dft(poly& f, bool inverse = false) {
	int n = f.size(); if (n == 1)return;

	static poly w{ 1 }, iw{ 1 };
	for (int m = w.size(); m < n / 2; m *= 2) {
		modint dw = mod_pow(proot, (mod - 1) / (4 * m)), dwinv = (modint)1 / dw;
		w.resize(m * 2); iw.resize(m * 2);
		for (int i = 0; i < m; i++)w[m + i] = w[i] * dw, iw[m + i] = iw[i] * dwinv;
	}
	if (!inverse) {
		for (int m = n; m >>= 1;) {
			for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
				for (int i = s; i < s + m; i++) {
					modint x = f[i], y = f[i + m] * w[k];
					f[i] = x + y, f[i + m] = x - y;
				}
			}
		}
	}
	else {
		for (int m = 1; m < n; m *= 2) {
			for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
				for (int i = s; i < s + m; i++) {
					modint x = f[i], y = f[i + m];
					f[i] = x + y, f[i + m] = (x - y) * iw[k];
				}
			}
		}
		modint n_inv = (modint)1 / (modint)n;
		for (modint& v : f)v *= n_inv;
	}
}
poly multiply(poly g, poly h) {
	int n = 1;
	int pi = 0, qi = 0;
	rep(i, g.size())if (g[i])pi = i;
	rep(i, h.size())if (h[i])qi = i;
	int sz = pi + qi + 2;
	while (n < sz)n *= 2;
	g.resize(n); h.resize(n);
	dft(g); dft(h);
	rep(i, n) {
		g[i] *= h[i];
	}
	dft(g, true);
	return g;
}
void solve() {
	int n; cin >> n; int m; cin >> m; m--;
	vector<ll> a(n);
	rep(i, n)cin >> a[i];
	vector<modint> c(n + 1);
	c[0] = 1;
	rep1(i, n) {
		c[i] = c[i - 1] * (modint)(m + i) / (modint)i;
	}
	vector<vector<int>> G(n);
	rep(i, n - 1) {
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	vector<int> nex(n);
	vector<int> depth(n);
	vector<int> par(n);
	function<int(int, int)>init_dfs = [&](int id, int fr)->int {
		par[id] = fr;
		nex[id] = id;
		int res = depth[id];
		for (int to : G[id])if (to != fr) {
			depth[to] = depth[id] + 1;
			int x = init_dfs(to, id);
			if (res < x) {
				res = x;
				nex[id] = to;
			}
		}
		return res;
	}; init_dfs(0, -1);
	vector<modint> ans(n);
	function<vector<modint>(int)> dfs = [&](int root)->vector<modint> {
		int cur = root;
		vector<int> ids;
		ids.push_back(cur);
		while (nex[cur] != cur) {
			cur = nex[cur]; ids.push_back(cur);
		}

		cur = root;
		int tmp = 0;
		while (nex[cur] != cur) {
			tmp++;
			for (int to : G[cur])if (to != nex[cur] && to != par[cur]) {
				vector<modint> nex = dfs(to);
				rep(j, nex.size()) {
					ans[ids[j + tmp]] -= nex[j];
				}
			}
			cur = nex[cur];
		}
		int dep = depth[cur] - depth[root];
		poly p(dep + 1);
		function<void(int, int)> subdfs = [&](int id, int fr) {
			int d = depth[id] - depth[root];
			p[d] += a[id];
			for (int to : G[id])if (to != fr) {
				subdfs(to, id);
			}
		}; subdfs(root, par[root]);
		poly coef;
		for (int i = dep; i >= 0; i--)coef.push_back(c[i]);
		poly r = multiply(p, coef);
		vector<modint> res(dep + 1);
		rep(i, dep + 1) {
			res[i] = r[i + dep];
			ans[ids[i]] += res[i];
		}
		return res;
	};
	dfs(0);
	rep(i, n) {
		if (i > 0)cout << " ";
		cout << ans[i];
	}
	cout << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(15);
	init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.9642857142857143
time_ms: 260
memory_kb: 65116
final_rank: 16

code_snippet: #include <bits/stdc++.h>
//#include <chrono>
//#pragma GCC optimize("Ofast")
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second
typedef long long ll;
typedef vector<ll> vec;
typedef vector<vec> mat;

ll N,M,H,W,Q,K,A,B;
string S;
typedef pair<ll, ll> P;
const ll INF = (1LL<<60);

template <unsigned long long mod > class modint{
public:
    ll x;
    constexpr modint(){x = 0;}
    constexpr modint(ll _x) : x((_x < 0 ? ((_x += (LLONG_MAX / mod) * mod) < 0 ? _x + (LLONG_MAX / mod) * mod : _x) : _x)%mod){}
    constexpr modint operator-(){
        return x == 0 ? 0 : mod - x;
    }
    constexpr modint& operator+=(const modint& a){
        if((x += a.x) >= mod) x -= mod;
        return *this;
    }
    constexpr modint operator+(const modint& a) const{
        return modint(*this) += a;
    }
    constexpr modint& operator-=(const modint& a){
        if((x -= a.x) < 0) x += mod;
        return *this;
    }
    constexpr modint operator-(const modint& a) const{
        return modint(*this) -= a;
    }
    constexpr modint& operator*=(const modint& a){
        (x *= a.x)%=mod;
        return *this;
    }
    constexpr modint operator*(const modint& a) const{
        return modint(*this) *= a;
    }
    constexpr modint pow(unsigned long long pw) const{
        modint res(1), comp(*this);
        while(pw){
            if(pw&1) res *= comp;
            comp *= comp;
            pw >>= 1;
        }
        return res;
    }
    //以下、modが素数のときのみ
    constexpr modint inv() const{
        return modint(*this).pow(mod - 2);
    }
    constexpr modint& operator/=(const modint &a){
        (x *= a.inv().x)%=mod;
        return *this;
    }
    constexpr modint operator/(const modint &a) const{
        return modint(*this) /= a;
    }
};
#define mod1 998244353
using mint = modint<mod1>;

ostream& operator<<(ostream& os, const mint& a){
    os << a.x;
    return os;
}
using vm = vector<mint>;
class NTT{
    const int root;

    void make_root_pow(int n, vm &root_pow){
        root_pow.resize(n + 1);
        mint new_root = mint(root).pow((mod1 - 1) / n);
        root_pow[0].x = 1;
        rep(i,n){
            root_pow[i + 1] = root_pow[i] * new_root;
        }
    }
    static void make_bit_reverse(int n, vector<int> &v){
        v.resize(n);
        iota(ALL(v), 0);
        for(int i = 1; (1<<i) <= n; ++i){
            int l = 1<<(i - 1), r = 1<<i;
            int plus = n >> i;
            for(int j = l; j < r; ++j){
                int temp = v[j - l] + plus;
                if(j < temp) swap(v[j], v[temp]);
            }
        }
    }
    static void dft(int n, vm &f, bool inv, vm &root_pow, vector<int> &id){
        vm g(n);
        rep(i,n) g[i] = f[id[i]];
        swap(f, g);
        for(int l = n / 2, len = 1; l >= 1; l /= 2, len *= 2){
            for(int i = 0; i < n; i += len * 2){
                rep(j, len){
                    mint z_f = (inv ? root_pow[n - l * j] : root_pow[l * j]) * f[i + len + j];
                    g[i + j] = f[i + j] + z_f;
                    g[i + len + j] = f[i + j] - z_f;
                }
            }
            swap(f, g);
        }
        if(inv) {
            mint n_inv = mint(n).inv();
            rep(i, n) f[i] *= n_inv;
        }
    }
public:
    NTT(int _x = 3) : root(_x){}
    vm convolution(vm &a, vm &b){
        int sz = a.size() + b.size() - 1, n = 1;
        while(sz > n) n *= 2;
        vm g(n), h(n), root_pow, gh(n);
        vector<int> id;
        copy(ALL(a), g.begin());
        copy(ALL(b), h.begin());
        make_root_pow(n, root_pow);
        make_bit_reverse(n, id);
        dft(n, g, false, root_pow, id);
        dft(n, h, false, root_pow, id);
        rep(i, n) gh[i] = g[i] * h[i];
        dft(n, gh, true, root_pow, id);
        gh.resize(sz);
        return gh;
    }
};
const int max_N = 200010;
vm comb(max_N), a(max_N), b(max_N, 0);
vec parent(max_N);
vector<set<int> > G(max_N);
void make_comb(ll m){
    comb[0] = 1;
    mint up(m), down(1);
    reps(i, 1, max_N){
        comb[i] = comb[i - 1] * up / down;
        up += 1;
        down += 1;
    }
}
void dfs(int v, int p, int k, priority_queue<P, vector<P>, greater<> > &pque){
    parent[v] = p;
    if(v != 0 && G[v].size() == 1){
        pque.emplace(k, v);
    }else{
        for(int to : G[v]){
            if(to != p) dfs(to, v, k + 1, pque);
        }
    }
}

void dfs_update(int v, int k, vec &nodes, vm &res){
    if(k < nodes.size()){
        a[v] += a[nodes[k]];
        b[v] -= res[k];
    }
    if(k != 0) {
        for (int to : G[v]) {
            if (to != parent[v]) {
                dfs_update(to, k - 1, nodes, res);
                return;
            }
        }
    }
}

int main() {
    cin>>N>>M;
    make_comb(M);
    rep(i, N) cin>>a[i].x;
    rep(i, N - 1){
        int u, v;
        cin>>u>>v;
        G[u].insert(v);
        G[v].insert(u);
    }
    priority_queue<P, vector<P>, greater<> > pque;
    dfs(0, 0, 0, pque);
    NTT ntt;
    while(!pque.empty()){
        P p = pque.top(); pque.pop();
        vec nodes(0);
        int now = p.se;
        //cout<<now<<endl;
        for( ; now != 0 && G[now].size() <= 2; now = parent[now]){
            nodes.push_back(now);
        }
        G[now].erase(*nodes.rbegin());
        bool last = G[now].empty();
        if(last) nodes.push_back(0);
        int sz = nodes.size();
        vm a_temp(0), comb_temp(sz);
        for(int v : nodes) a_temp.emplace_back(a[v]);
        copy(comb.begin(), comb.begin() + sz, comb_temp.begin());
        //rep(i, sz) cout<<a_temp[i]<<' '<<comb_temp[i]<<endl;
        vm res = ntt.convolution(a_temp, comb_temp);
        res.resize(sz);
        rep(i, sz) b[nodes[i]] += res[i];
        if(!last) dfs_update(now, sz, nodes, res);
    }
    rep(i, N) {
        cout<<b[i];
        if(i != N - 1) cout<<' ';
    }
    cout<<endl;
}
accuracy: 1
time_ms: 450
memory_kb: 50884
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}


constexpr int bmds(int x){
  const int v[] = {1012924417, 924844033, 998244353,
                   897581057, 645922817};
  return v[x];
}
constexpr int brts(int x){
  const int v[] = {5, 5, 3, 3, 3};
  return v[x];
}

template<int X>
struct NTT{
  static constexpr int md = bmds(X);
  static constexpr int rt = brts(X);
  using M = Mint<int, md>;
  vector< vector<M> > rts,rrts;

  void ensure_base(int n){
    if((int)rts.size()>=n) return;
    rts.resize(n);rrts.resize(n);
    for(int i=1;i<n;i<<=1){
      if(!rts[i].empty()) continue;
      M w=M(rt).pow((md-1)/(i<<1));
      M rw=w.inv();
      rts[i].resize(i);rrts[i].resize(i);
      rts[i][0]=M(1);rrts[i][0]=M(1);
      for(int k=1;k<i;k++){
        rts[i][k]=rts[i][k-1]*w;
        rrts[i][k]=rrts[i][k-1]*rw;
      }
    }
  }

  void ntt(vector<M> &as,bool f){
    int n=as.size();
    assert((n&(n-1))==0);
    ensure_base(n);

    for(int i=0,j=1;j+1<n;j++){
      for(int k=n>>1;k>(i^=k);k>>=1);
      if(i>j) swap(as[i],as[j]);
    }

    for(int i=1;i<n;i<<=1){
      for(int j=0;j<n;j+=i*2){
        for(int k=0;k<i;k++){
          M z=as[i+j+k]*(f?rrts[i][k]:rts[i][k]);
          as[i+j+k]=as[j+k]-z;
          as[j+k]+=z;
        }
      }
    }

    if(f){
      M tmp=M(n).inv();
      for(int i=0;i<n;i++) as[i]*=tmp;
    }
  }

  vector<M> multiply(vector<M> as,vector<M> bs){
    int need=as.size()+bs.size()-1;
    int sz=1;
    while(sz<need) sz<<=1;
    as.resize(sz,M(0));
    bs.resize(sz,M(0));

    ntt(as,0);ntt(bs,0);
    for(int i=0;i<sz;i++) as[i]*=bs[i];
    ntt(as,1);

    as.resize(need);
    return as;
  }

  vector<int> multiply(vector<int> as,vector<int> bs){
    vector<M> am(as.size()),bm(bs.size());
    for(int i=0;i<(int)am.size();i++) am[i]=M(as[i]);
    for(int i=0;i<(int)bm.size();i++) bm[i]=M(bs[i]);
    vector<M> cm=multiply(am,bm);
    vector<int> cs(cm.size());
    for(int i=0;i<(int)cs.size();i++) cs[i]=cm[i].v;
    return cs;
  }
};
template<int X> constexpr int NTT<X>::md;
template<int X> constexpr int NTT<X>::rt;


template<typename T>
struct FormalPowerSeries{
  using Poly = vector<T>;
  using Conv = function<Poly(Poly, Poly)>;
  Conv conv;
  FormalPowerSeries(Conv conv):conv(conv){}

  Poly pre(const Poly &as,int deg){
    return Poly(as.begin(),as.begin()+min((int)as.size(),deg));
  }

  Poly add(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,T(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]+=bs[i];
    return cs;
  }

  Poly sub(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,T(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]-=bs[i];
    return cs;
  }

  Poly mul(Poly as,Poly bs){
    return conv(as,bs);
  }

  Poly mul(Poly as,T k){
    for(auto &a:as) a*=k;
    return as;
  }

  // F(0) must not be 0
  Poly inv(Poly as,int deg){
    assert(as[0]!=T(0));
    Poly rs({T(1)/as[0]});
    for(int i=1;i<deg;i<<=1)
      rs=pre(sub(add(rs,rs),mul(mul(rs,rs),pre(as,i<<1))),i<<1);
    return rs;
  }

  // not zero
  Poly div(Poly as,Poly bs){
    while(as.back()==T(0)) as.pop_back();
    while(bs.back()==T(0)) bs.pop_back();
    if(bs.size()>as.size()) return Poly();
    reverse(as.begin(),as.end());
    reverse(bs.begin(),bs.end());
    int need=as.size()-bs.size()+1;
    Poly ds=pre(mul(as,inv(bs,need)),need);
    reverse(ds.begin(),ds.end());
    return ds;
  }

  Poly mod(Poly as,Poly bs){
    if(as==Poly(as.size(),0)) return Poly({0});
    as=sub(as,mul(div(as,bs),bs));
    if(as==Poly(as.size(),0)) return Poly({0});
    while(as.back()==T(0)) as.pop_back();
    return as;
  }

  // F(0) must be 1
  Poly sqrt(Poly as,int deg){
    assert(as[0]==T(1));
    T inv2=T(1)/T(2);
    Poly ss({T(1)});
    for(int i=1;i<deg;i<<=1){
      ss=pre(add(ss,mul(pre(as,i<<1),inv(ss,i<<1))),i<<1);
      for(T &x:ss) x*=inv2;
    }
    return ss;
  }

  Poly diff(Poly as){
    int n=as.size();
    Poly rs(n-1);
    for(int i=1;i<n;i++) rs[i-1]=as[i]*T(i);
    return rs;
  }

  Poly integral(Poly as){
    int n=as.size();
    Poly rs(n+1);
    rs[0]=T(0);
    for(int i=0;i<n;i++) rs[i+1]=as[i]/T(i+1);
    return rs;
  }

  // F(0) must be 1
  Poly log(Poly as,int deg){
    return pre(integral(mul(diff(as),inv(as,deg))),deg);
  }

  // F(0) must be 0
  Poly exp(Poly as,int deg){
    Poly f({T(1)});
    as[0]+=T(1);
    for(int i=1;i<deg;i<<=1)
      f=pre(mul(f,sub(pre(as,i<<1),log(f,i<<1))),i<<1);
    return f;
  }

  Poly partition(int n){
    Poly rs(n+1);
    rs[0]=T(1);
    for(int k=1;k<=n;k++){
      if(1LL*k*(3*k+1)/2<=n) rs[k*(3*k+1)/2]+=T(k%2?-1LL:1LL);
      if(1LL*k*(3*k-1)/2<=n) rs[k*(3*k-1)/2]+=T(k%2?-1LL:1LL);
    }
    return inv(rs,n+1);
  }

  Poly bernoulli(int n){
    Poly rs(n+1,1);
    for(int i=1;i<=n;i++) rs[i]=rs[i-1]/T(i+1);
    rs=inv(rs,n+1);
    T tmp(1);
    for(int i=1;i<=n;i++){
      tmp*=T(i);
      rs[i]*=tmp;
    }
    return rs;
  }
};


struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;


struct Centroid{
  vector<int> sz,dead;
  vector< vector<int> > G;
  Centroid(){}
  Centroid(int n):sz(n,1),dead(n,0),G(n){}

  void add_edge(int u,int v){
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  int dfs(int v,int p){
    sz[v]=1;
    for(int u:G[v])
      if(u!=p&&!dead[u]) sz[v]+=dfs(u,v);
    return sz[v];
  }

  void find(int v,int p,int tmp,vector<int> &cs) {
    int ok=1;
    for (int u:G[v]){
      if(u==p||dead[u]) continue;
      find(u,v,tmp,cs);
      ok&=(sz[u]<=tmp/2);
    }
    ok&=(tmp-sz[v]<=tmp/2);
    if(ok) cs.push_back(v);
  }

  vector<int> build(int r) {
    int tmp=dfs(r,-1);
    vector<int> cs;
    find(r,-1,tmp,cs);
    return cs;
  }

  void disable(int v){
    dead[v]=1;
  }

  void enable(int v){
    dead[v]=0;
  }

  int alive(int v){
    return !dead[v];
  }
};


template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}

//INSERT ABOVE HERE
signed main(){
  NTT<2> ntt;
  using M = decltype(ntt)::M;
  auto conv=[&](auto as,auto bs){return ntt.multiply(as,bs);};
  FormalPowerSeries<M> FPS(conv);
  using Poly = decltype(FPS)::Poly;

  int n,m;
  cin>>n>>m;

  Poly as(n);
  for(int i=0;i<n;i++) cin>>as[i].v;

  Centroid G(n+1);
  G.add_edge(n,0);
  for(int i=1;i<n;i++){
    int u,v;
    cin>>u>>v;
    G.add_edge(u,v);
  }

  vector<int> par(n+1,-1);
  {
    queue<int> que;
    que.emplace(n);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int u:G.G[v]){
        if(u==par[v]) continue;
        par[u]=v;
        que.emplace(u);
      }
    }
  }

  vector<int> dead(n+1,0);
  auto disable=
    [&](int k){
      dead[k]=1;
      G.disable(k);
    };
  disable(n);

  const int deg = 1<<18;
  Poly ps(n,M(1));
  ps=FPS.exp(FPS.mul(FPS.log(ps,deg),M(m)),deg);

  queue<int> que;
  que.emplace(G.build(0)[0]);

  Poly ans(n);
  while(!que.empty()){
    int r=que.front();que.pop();

    Poly qs;
    MFP([&](auto dfs,int v,int p,int h)->void{
          while(!(h<(int)qs.size())) qs.emplace_back(0);
          qs[h]+=as[v];
          for(int u:G.G[v]){
            if(u==p) continue;
            if(dead[u]) continue;
            dfs(u,v,h+1);
          }
        })(r,par[r],0);
    reverse(qs.begin(),qs.end());

    vector<int> bs;
    int p=r;
    while(~p&&!dead[p]){
      bs.emplace_back(p);
      p=par[p];
    }

    int len=qs.size()-1;
    qs.resize(len+bs.size(),M(0));
    auto rs=FPS.mul(FPS.pre(ps,qs.size()),qs);

    for(int i=0;i<(int)bs.size();i++) ans[bs[i]]+=rs[len+i];

    disable(r);
    for(int u:G.G[r])
      if(!dead[u]) que.emplace(G.build(u)[0]);
  }

  for(int i=0;i<n;i++){
    if(i) cout<<" ";
    cout<<ans[i];
  }
  cout<<endl;
  return 0;
}
accuracy: 1
time_ms: 1290
memory_kb: 66896
final_rank: 14

code_snippet: #include <bits/extc++.h>

template <uint32_t Modulus>
struct modular {
  static_assert(int(Modulus) > 0, "Modulus must be in the range [1, 2^31)");
  static constexpr int modulus() { return Modulus; }

  modular() : v(0) {}
  modular(int64_t x) : v(x % Modulus) {
    if (int(v) < 0) v += Modulus;
  }

  explicit operator int() const { return v; }
  modular& operator++() { return ++v == Modulus ? v = 0 : 0, *this; }
  modular& operator--() { return --(v ? v : v = Modulus), *this; }
  modular operator+() const { return *this; }
  modular operator-() const {
    modular res;
    res.v = v ? Modulus - v : 0;
    return res;
  }
  modular& operator*=(modular b) {
    v = uint64_t(v) * b.v % Modulus;
    return *this;
  }
  modular& operator/=(modular b) {
    auto [x, gcd] = extgcd(b.v, Modulus);
    assert(gcd == 1);
    return *this *= x;
  }
  modular& operator+=(modular b) {
    v += b.v - Modulus;
    if (int(v) < 0) v += Modulus;
    return *this;
  }
  modular& operator-=(modular b) {
    v -= b.v;
    if (int(v) < 0) v += Modulus;
    return *this;
  }

  friend modular operator++(modular& a, int) {
    return std::exchange(a, ++modular(a));
  }
  friend modular operator--(modular& a, int) {
    return std::exchange(a, --modular(a));
  }
  friend modular operator*(modular a, modular b) { return a *= b; }
  friend modular operator/(modular a, modular b) { return a /= b; }
  friend modular operator+(modular a, modular b) { return a += b; }
  friend modular operator-(modular a, modular b) { return a -= b; }
  friend std::istream& operator>>(std::istream& is, modular& b) {
    int64_t x;
    return is >> x, b = x, is;
  }
  friend std::ostream& operator<<(std::ostream& os, modular b) {
    return os << b.v;
  }
  friend bool operator==(modular a, modular b) { return a.v == b.v; }
  friend bool operator!=(modular a, modular b) { return a.v != b.v; }

 private:
  static std::pair<int, int> extgcd(int a, int b) {
    std::array x{1, 0};
    while (b) {
      int q = a / b;
      std::swap(x[0] -= q * x[1], x[1]);
      std::swap(a -= q * b, b);
    }
    return {x[0], a};
  }

  uint32_t v;
};

template <class T, class U, class BinaryOperation = std::multiplies<>>
constexpr T power(T a, U n, T init = 1,
                  BinaryOperation binary_op = BinaryOperation{}) {
  static_assert(std::is_integral_v<U> and not std::is_same_v<U, bool>);
  assert(n >= 0);
  while (n) {
    if (n & 1) init = binary_op(init, a);
    if (n >>= 1) a = binary_op(a, a);
  }
  return init;
}

template <class T>
void ntt(std::vector<T>& a, bool inverse) {
  int n = size(a);
  assert((n & (n - 1)) == 0);
  if (n < 2) return;
  assert((T::modulus() - 1) % n == 0);
  static std::vector<T> w{1}, iw{1};
  for (int m = size(w); m < n / 2; m *= 2) {
    static T root = 2;
    while (power(root, (T::modulus() - 1) / 2) == 1) ++root;
    T dw = power(root, (T::modulus() - 1) / (4 * m)), idw = 1 / dw;
    w.resize(2 * m), iw.resize(2 * m);
    for (int i = 0; i < m; ++i) w[m + i] = w[i] * dw, iw[m + i] = iw[i] * idw;
  }
  if (not inverse) {
    for (int m = n; m >>= 1;) {
      for (int s = 0, k = 0; s < n; s += 2 * m, ++k) {
        for (int i = s, j = s + m; i < s + m; ++i, ++j) {
          T x = a[i], y = a[j] * w[k];
          a[i] = x + y, a[j] = x - y;
        }
      }
    }
  } else {
    for (int m = 1; m < n; m *= 2) {
      for (int s = 0, k = 0; s < n; s += 2 * m, ++k) {
        for (int i = s, j = s + m; i < s + m; ++i, ++j) {
          T x = a[i], y = a[j];
          a[i] = x + y, a[j] = (x - y) * iw[k];
        }
      }
    }
    auto inv = 1 / T(n);
    for (auto&& e : a) e *= inv;
  }
}
template <class T>
std::vector<T> operator*(std::vector<T> a, std::vector<T> b) {
  if (empty(a) or empty(b)) return {};
  int n = size(a), m = size(b), sz = 1 << std::__lg(2 * (n + m - 1) - 1);
  if (std::min(n, m) < 30) {
    std::vector<T> res(n + m - 1);
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < m; ++j) res[i + j] += a[i] * b[j];
    return res;
  }
  bool eq = a == b;
  a.resize(sz), ntt(a, false);
  if (eq)
    b = a;
  else
    b.resize(sz), ntt(b, false);
  for (int i = 0; i < sz; ++i) a[i] *= b[i];
  ntt(a, true), a.resize(n + m - 1);
  return a;
}

struct graph {
  struct edge {
    static inline bool cost;  // dummy
    int src, dst;

    int operator-(int v) const {
      assert(v == src or v == dst);
      return src ^ dst ^ v;
    }
  };

  int n, m;
  std::vector<edge> edges;
  std::vector<std::vector<std::pair<int, int>>> adj;
  std::function<bool(int)> ignore;

  graph(int _n = 0) : n(_n), m(0), adj(n), ignore([](int) { return false; }) {}

  int add(const edge& e, bool directed) {
    assert(0 <= e.src), assert(e.src < n);
    assert(0 <= e.dst), assert(e.dst < n);
    edges.push_back(e);
    adj[e.src].emplace_back(m, e.dst);
    if (not directed) adj[e.dst].emplace_back(m, e.src);
    return m++;
  }
};

struct dfs_forest : graph {
  using cost_t = decltype(edge::cost);

  std::vector<int> root, pv, pe, sz, depth, min_depth, last, order, in, out;
  std::vector<cost_t> dist;
  int trials;

  dfs_forest(int _n = 0) : graph(_n), dist(n), trials(0) {
    for (auto p : {&root, &pv, &pe, &sz, &depth, &min_depth, &last, &in, &out})
      p->assign(n, -1);
  }

  int add(const edge& e) { return graph::add(e, false); }
  void build(int r, bool clear_order = true) {
    assert(0 <= r), assert(r < n);
    root[r] = r, pv[r] = pe[r] = -1, depth[r] = 0, dist[r] = cost_t{};
    if (clear_order) order.clear();
    dfs(r);
    ++trials;
  }
  void build() {
    fill(begin(root), end(root), -1);
    for (int v = 0; v < n; ++v)
      if (root[v] == -1) build(v, v == 0);
  }
  int deeper(int id) const {
    assert(0 <= id), assert(id < m), assert(not ignore(id));
    int u = edges[id].src, v = edges[id].dst;
    return depth[u] < depth[v] ? v : u;
  }
  bool is_tree_edge(int id) const {
    assert(0 <= id), assert(id < m), assert(not ignore(id));
    return id == pe[deeper(id)];
  }
  bool is_ancestor(int u, int v) const {
    assert(0 <= u), assert(u < n);
    assert(0 <= v), assert(v < n);
    return in[u] <= in[v] and out[v] <= out[u];
  }

 private:
  void dfs(int v) {
    sz[v] = 1, min_depth[v] = depth[v], last[v] = trials;
    in[v] = size(order), order.push_back(v);
    for (auto [id, u] : adj[v]) {
      if (ignore(id) or id == pe[v]) continue;
      if (last[u] == trials) {
        min_depth[v] = std::min(min_depth[v], depth[u]);
        continue;
      }
      root[u] = root[v], pv[u] = v, pe[u] = id, depth[u] = depth[v] + 1;
      dist[u] = dist[v] + edges[id].cost;
      dfs(u);
      sz[v] += sz[u], min_depth[v] = std::min(min_depth[v], min_depth[u]);
    }
    out[v] = size(order);
  }
};

template <class F>
struct y_combinator : private F {
  y_combinator(F f) : F(f) {}
  template <class... Args>
  decltype(auto) operator()(Args&&... args) const {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};

int main() {
  using namespace std;
  cin.tie(nullptr)->sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  --m;
  vector<int> a(n);
  for (auto&& e : a) cin >> e;
  dfs_forest g(n);
  for (int _ = n - 1; _--;) {
    int u, v;
    cin >> u >> v;
    g.add({u, v});
  }
  g.build();
  vector<int> h(n);
  for_each(rbegin(g.order), rend(g.order), [&](int v) {
    h[v] = 1;
    for (auto [id, u] : g.adj[v]) {
      if (id == g.pe[v]) continue;
      h[v] = max(h[v], h[u] + 1);
    }
    sort(begin(g.adj[v]), end(g.adj[v]), [&](auto x, auto y) {
      int xu = x.second, yu = y.second;
      return h[xu] * (xu != g.pv[v]) > h[yu] * (yu != g.pv[v]);
    });
  });

  using mint = modular<998244353>;
  vector<mint> coeff(n);
  for (int i = 0; i < n; ++i) coeff[i] = i ? coeff[i - 1] * (m + i) / i : 1;

  vector<mint> buf;
  vector<mint> ans(n);
  vector<int> l(n, -1), r(n, -1);
  y_combinator([&](auto&& self, int v) -> void {
    if (l[v] == -1) {
      int sz = size(buf);
      buf.resize(sz + h[v]);
      for (int i = g.in[v]; i < g.out[v]; ++i) {
        int u = g.order[i];
        buf[sz + (g.depth[u] - g.depth[v])] += a[u];
      }
      auto t = vector(rbegin(buf), rend(buf) - sz) *
               vector(begin(coeff), begin(coeff) + h[v]);
      t.resize(h[v]);
      move(begin(t), end(t), rbegin(buf));
      l[v] = sz, r[v] = size(buf);
      assert(r[v] - l[v] == h[v]);
    }
    ans[v] = buf[l[v]];
    for (int i = 1; i < int(size(g.adj[v])); ++i) {
      auto [id, u] = g.adj[v][i];
      if (id == g.pe[v]) continue;
      assert(l[u] == -1);
      self(u);
      for (int j = l[u]; j < r[u]; ++j) buf[l[v] + 1 + (j - l[u])] -= buf[j];
    }
    if (int u = g.adj[v][0].second; u != g.pv[v]) {
      l[u] = l[v] + 1, r[u] = l[u] + h[u];
      self(u);
    }
    for (int i = 1; i < int(size(g.adj[v])); ++i) {
      auto [id, u] = g.adj[v][i];
      if (id == g.pe[v]) continue;
      for (int j = l[u]; j < r[u]; ++j) buf[l[v] + 1 + (j - l[u])] += buf[j];
    }
  })(0);

  for (int v = 0; v < n; ++v) cout << ans[v] << " \n"[v == n - 1];
}
accuracy: 1
time_ms: 140
memory_kb: 39760
final_rank: 3

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
constexpr int inf=1e9+7;
constexpr ll longinf=1LL<<60 ;
constexpr ll mod=998244353 ;

template< int mod >
struct NumberTheoreticTransform {

  vector< int > rev, rts;
  int base, max_base, root;

  NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
    assert(mod >= 3 && mod % 2 == 1);
    auto tmp = mod - 1;
    max_base = 0;
    while(tmp % 2 == 0) tmp >>= 1, max_base++;
    root = 2;
    while(mod_pow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mod_pow(root, mod - 1) == 1);
    root = mod_pow(root, (mod - 1) >> max_base);
  }

  inline int mod_pow(int x, int n) {
    int ret = 1;
    while(n > 0) {
      if(n & 1) ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline int inverse(int x) {
    return mod_pow(x, mod - 2);
  }

  inline unsigned add(unsigned x, unsigned y) {
    x += y;
    if(x >= mod) x -= mod;
    return x;
  }

  inline unsigned mul(unsigned a, unsigned b) {
    return 1ull * a * b % (unsigned long long) mod;
  }

  void ensure_base(int nbase) {
    if(nbase <= base) return;
    rev.resize(1 << nbase);
    rts.resize(1 << nbase);
    for(int i = 0; i < (1 << nbase); i++) {
      rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
    }
    assert(nbase <= max_base);
    while(base < nbase) {
      int z = mod_pow(root, 1 << (max_base - 1 - base));
      for(int i = 1 << (base - 1); i < (1 << base); i++) {
        rts[i << 1] = rts[i];
        rts[(i << 1) + 1] = mul(rts[i], z);
      }
      ++base;
    }
  }


  void ntt(vector< int > &a) {
    const int n = (int) a.size();
    assert((n & (n - 1)) == 0);
    int zeros = __builtin_ctz(n);
    ensure_base(zeros);
    int shift = base - zeros;
    for(int i = 0; i < n; i++) {
      if(i < (rev[i] >> shift)) {
        swap(a[i], a[rev[i] >> shift]);
      }
    }
    for(int k = 1; k < n; k <<= 1) {
      for(int i = 0; i < n; i += 2 * k) {
        for(int j = 0; j < k; j++) {
          int z = mul(a[i + j + k], rts[j + k]);
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
      }
    }
  }


  vector< int > multiply(vector< int > a, vector< int > b) {
    int need = a.size() + b.size() - 1;
    int nbase = 1;
    while((1 << nbase) < need) nbase++;
    ensure_base(nbase);
    int sz = 1 << nbase;
    a.resize(sz, 0);
    b.resize(sz, 0);
    ntt(a);
    ntt(b);
    int inv_sz = inverse(sz);
    for(int i = 0; i < sz; i++) {
      a[i] = mul(a[i], mul(b[i], inv_sz));
    }
    reverse(a.begin() + 1, a.end());
    ntt(a);
    a.resize(need);
    return a;
  }
};

NumberTheoreticTransform<998244353> ntt;


int w[202020],chl[202020], depth[202020];
vector<int> v[202020];
void dfs1(int x, int p) {
    for(auto to : v[x]) {
        if(to == p)continue;
        depth[to] = depth[x] + 1;
        dfs1(to,x);
    }
}

int dfs2(int x, int p) {
    chl[x] = -1;
    int ma = depth[x];
    for(auto to : v[x]) {
        if(to == p)continue;
        int ret = dfs2(to,x);
        if(ret>ma){
            ma = ret;
            chl[x] = to;
        }
    }
    return ma;
}

void dfs3(int x,int p, int d, vector<int>& a){
    a[d] += w[x];
    if(a[d]>=mod)a[d]-=mod;
    for(auto to:v[x]){
        if(to==p)continue;
        dfs3(to,x,d+1,a);
    }
}
int used[202020];
ll ans[202020];
vector<int> b;

void solve(int x, int p) {
    if(!used[x]){
        depth[x] = 0;
        dfs1(x, p);
        int sz = dfs2(x, p) + 1;
        vector<int> a(sz);
        dfs3(x, p, 0, a);
        vector<int> c(sz);
        rep(i,sz)c[i] = b[sz-i-1];
        auto ret = ntt.multiply(a, c);
        int cur = x, idx = sz - 1;
        while(cur != -1){
            ans[cur] += ret[idx];
            ++idx;
            used[cur] = 1;
            cur = chl[cur];
        }
        if(p != -1) {
            int cur = chl[p], idx = sz-1;
            while(cur != -1){
                if(idx == 2 * sz - 1)break;
                ans[cur] += mod - ret[idx];
                ++idx;
                cur = chl[cur];
            }
        }
    }
    for(auto to : v[x]){
        if(to == p)continue;
        solve(to, x);
    }
}

vector<ll> inv,fact,invfact;
void mod_build(int n=101010){
    fact.resize(n+1);
    inv.resize(n+1);
    invfact.resize(n+1);
    fact[0]=inv[0]=invfact[0]=1;
    inv[1]=1;
    rep(i,n){
        fact[i+1]=fact[i]*(i+1)%mod;
        if(i>0)inv[i+1]=mod-inv[mod%(i+1)]*(mod/(i+1))%mod;
        invfact[i+1]=invfact[i]*inv[i+1]%mod;
    }
}
ll perm(int n,int k){
    if(n<0||k<0||k>n)return 0;
    return fact[n]*invfact[n-k]%mod;
}
ll comb(int n,int k){
    if(n<0||k<0||k>n)return 0;
    return (fact[n]*invfact[n-k]%mod)*invfact[k]%mod;
}
ll powmod(ll n,ll k){
    k%=mod-1;
    if(k<0)k+=mod-1;
    ll ret=1;
    while(k){
        if(k&1)ret=ret*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return ret;
}
int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m;
    cin>>n >> m;
    rep(i,n)cin>>w[i];
    rep(i,n-1){
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    mod_build(1234567);
    b.resize(n+1);
    ll cur = 1;
    rep(i,n+1){
        b[i] = cur;
        cur *= m + i;
        cur %= mod;
        cur *= inv[i+1];
        cur %= mod;
    }
    solve(0,-1);
    rep(i,n)cout<<ans[i]%mod << " \n"[i+1==n];
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 65940
final_rank: 7

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
constexpr int inf=1e9+7;
constexpr ll longinf=1LL<<60 ;
constexpr ll mod=998244353 ;

template< int mod >
struct NumberTheoreticTransform {

  vector< int > rev, rts;
  int base, max_base, root;

  NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
    assert(mod >= 3 && mod % 2 == 1);
    auto tmp = mod - 1;
    max_base = 0;
    while(tmp % 2 == 0) tmp >>= 1, max_base++;
    root = 2;
    while(mod_pow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mod_pow(root, mod - 1) == 1);
    root = mod_pow(root, (mod - 1) >> max_base);
  }

  inline int mod_pow(int x, int n) {
    int ret = 1;
    while(n > 0) {
      if(n & 1) ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline int inverse(int x) {
    return mod_pow(x, mod - 2);
  }

  inline unsigned add(unsigned x, unsigned y) {
    x += y;
    if(x >= mod) x -= mod;
    return x;
  }

  inline unsigned mul(unsigned a, unsigned b) {
    return 1ull * a * b % (unsigned long long) mod;
  }

  void ensure_base(int nbase) {
    if(nbase <= base) return;
    rev.resize(1 << nbase);
    rts.resize(1 << nbase);
    for(int i = 0; i < (1 << nbase); i++) {
      rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
    }
    assert(nbase <= max_base);
    while(base < nbase) {
      int z = mod_pow(root, 1 << (max_base - 1 - base));
      for(int i = 1 << (base - 1); i < (1 << base); i++) {
        rts[i << 1] = rts[i];
        rts[(i << 1) + 1] = mul(rts[i], z);
      }
      ++base;
    }
  }


  void ntt(vector< int > &a) {
    const int n = (int) a.size();
    assert((n & (n - 1)) == 0);
    int zeros = __builtin_ctz(n);
    ensure_base(zeros);
    int shift = base - zeros;
    for(int i = 0; i < n; i++) {
      if(i < (rev[i] >> shift)) {
        swap(a[i], a[rev[i] >> shift]);
      }
    }
    for(int k = 1; k < n; k <<= 1) {
      for(int i = 0; i < n; i += 2 * k) {
        for(int j = 0; j < k; j++) {
          int z = mul(a[i + j + k], rts[j + k]);
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
      }
    }
  }


  vector< int > multiply(vector< int > a, vector< int > b) {
    int need = a.size() + b.size() - 1;
    int nbase = 1;
    while((1 << nbase) < need) nbase++;
    ensure_base(nbase);
    int sz = 1 << nbase;
    a.resize(sz, 0);
    b.resize(sz, 0);
    ntt(a);
    ntt(b);
    int inv_sz = inverse(sz);
    for(int i = 0; i < sz; i++) {
      a[i] = mul(a[i], mul(b[i], inv_sz));
    }
    reverse(a.begin() + 1, a.end());
    ntt(a);
    a.resize(need);
    return a;
  }
};

NumberTheoreticTransform<998244353> ntt;


int w[202020],chl[202020], depth[202020];
vector<int> v[202020];
void dfs1(int x, int p) {
    for(auto to : v[x]) {
        if(to == p)continue;
        depth[to] = depth[x] + 1;
        dfs1(to,x);
    }
}

int dfs2(int x, int p) {
    chl[x] = -1;
    int ma = depth[x];
    for(auto to : v[x]) {
        if(to == p)continue;
        int ret = dfs2(to,x);
        if(ret>ma){
            ma = ret;
            chl[x] = to;
        }
    }
    return ma;
}

void dfs3(int x,int p, int d, vector<int>& a){
    a[d] += w[x];
    if(a[d]>=mod)a[d]-=mod;
    for(auto to:v[x]){
        if(to==p)continue;
        dfs3(to,x,d+1,a);
    }
}
int used[202020];
ll ans[202020];
vector<int> b;

void solve(int x, int p) {
    if(!used[x]){
        depth[x] = 0;
        dfs1(x, p);
        int sz = dfs2(x, p) + 1;
        vector<int> a(sz);
        dfs3(x, p, 0, a);
        vector<int> c(sz);
        rep(i,sz)c[i] = b[sz-i-1];
        auto ret = ntt.multiply(a, c);
        int cur = x, idx = sz - 1;
        while(cur != -1){
            ans[cur] += ret[idx];
            ++idx;
            used[cur] = 1;
            cur = chl[cur];
        }
        if(p != -1) {
            int cur = chl[p], idx = sz-1;
            while(cur != -1){
                ans[cur] += mod - ret[idx];
                ++idx;
                used[cur] = 1;
                cur = chl[cur];
            }
        }
    }
    for(auto to : v[x]){
        if(to == p)continue;
        solve(to, x);
    }
}

vector<ll> inv,fact,invfact;
void mod_build(int n=101010){
    fact.resize(n+1);
    inv.resize(n+1);
    invfact.resize(n+1);
    fact[0]=inv[0]=invfact[0]=1;
    inv[1]=1;
    rep(i,n){
        fact[i+1]=fact[i]*(i+1)%mod;
        if(i>0)inv[i+1]=mod-inv[mod%(i+1)]*(mod/(i+1))%mod;
        invfact[i+1]=invfact[i]*inv[i+1]%mod;
    }
}
ll perm(int n,int k){
    if(n<0||k<0||k>n)return 0;
    return fact[n]*invfact[n-k]%mod;
}
ll comb(int n,int k){
    if(n<0||k<0||k>n)return 0;
    return (fact[n]*invfact[n-k]%mod)*invfact[k]%mod;
}
ll powmod(ll n,ll k){
    k%=mod-1;
    if(k<0)k+=mod-1;
    ll ret=1;
    while(k){
        if(k&1)ret=ret*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return ret;
}
int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m;
    cin>>n >> m;
    rep(i,n)cin>>w[i];
    rep(i,n-1){
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    mod_build(1234567);
    b.resize(n+1);
    ll cur = 1;
    rep(i,n+1){
        b[i] = cur;
        cur *= m + i;
        cur %= mod;
        cur *= inv[i+1];
        cur %= mod;
    }
    solve(0,-1);
    rep(i,n)cout<<ans[i]%mod << " \n"[i+1==n];
    return 0;
}
accuracy: 0.10714285714285714
time_ms: 10
memory_kb: 38124
final_rank: 20

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
template<class T>
void dmp(T a){
	rep(i,a.size()) cout << a[i] << " ";
	cout << endl;
}
template<class T>
bool chmax(T&a, T b){
	if(a < b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a, T b){
	if(a > b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 998244353;
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}


ll rui[200005];
ll modpow(ll x,ll n){
	ll res=1;
	while(n>0){
		if(n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}
ll F[200005],R[200005];
void make(){
	F[0] = 1;
	for(int i=1;i<200005;i++) F[i] = F[i-1]*i%mod;
	for(int i=0;i<200005;i++) R[i] = modpow(F[i],mod-2);
}
ll C(int a,int b){
	return F[a]*R[b]%mod*R[a-b]%mod;
}
int up[200005], n, sub[200005], dep[200005], maxdep[200005];
vector<int>edge[200005];
ll m, a[200005];
void dfs(int v, int u){
	up[v] = u;
	sub[v] = 1;
	if(u == -1) dep[v] = 0; else dep[v] = dep[u]+1;
	maxdep[v] = dep[v];
	for(const auto at:edge[v]){
		if(at == u) continue;
		dfs(at, v);
		sub[v] += sub[at];
		chmax(maxdep[v], maxdep[at]);
	}
}
int cmp[200005], num[200005], len[200005];
void dfs2(int v, int u, int d){
	P p = mp(-1, -1);
	for(const auto at:edge[v]){
		if(at == u) continue;
		chmax(p, mp(sub[at], at));
	}
	for(const auto at:edge[v]){
		if(at == u) continue;
		if(at == p.sc){
			cmp[at] = cmp[v], num[at] = num[v]+1;
		}
		else{
			cmp[at] = at, num[at] = 0;
		}
		dfs2(at, v, d+1);
	}
}
template<const int md>
struct ntt{
	inline void add(int &a, int b) { a += b; if(a >= md) a -= md; }
	inline void sub(int &a, int b) { a -= b; if(a < 0) a += md; }
	inline int mul(int a, int b) { return (int)((ll)a*b%md); }
	inline int power(int a, long long b) {
		int res = 1;
		while (b > 0) {
			if (b & 1) res = mul(res, a);
	    	a = mul(a, a);
			b >>= 1;
		}
		return res;
	}
	inline int inv(int a) {
		a %= md;
		if (a < 0) a += md;
		int b = md, u = 0, v = 1;
		while (a) {
			int t = b / a;
			b -= t * a; swap(a, b);
			u -= t * v; swap(u, v);
		}
		assert(b == 1);
		if (u < 0) u += md;
		return u;
	}
	
 	int max_base, root;
	vector<int> dw, idw;
	ntt() {
		int tmp = md - 1;
		max_base = 0;
		while (tmp % 2 == 0) {
			tmp /= 2;
			max_base++;
		}
		root = 2;
		while (power(root, (md-1)>>1) == 1) root++;
		dw.resize(max_base); idw.resize(max_base);
		rep(i, max_base){
			sub(dw[i], power(root, (md-1) >> (i+2)));
			idw[i] = inv(dw[i]);
		}
	}
	void fft(vector<int> &a, bool inv) {
		const int n = a.size();
		assert((n & (n - 1)) == 0);
		assert(__builtin_ctz(n) <= max_base);
		if(!inv){
			for(int m=n;m>>=1;){
				int w = 1;
				for(int s=0,k=0; s<n; s += 2*m){
					for(int i=s, j=s+m ; i < s+m; ++i, ++j) {
						int x = a[i], y = mul(a[j], w);
						a[j] = (x>=y?x-y:x+md-y);
						a[i] = (x+y>=md?x+y-md:x+y);
					}
					w = mul(w, dw[__builtin_ctz(++k)]);
				}
			}
		}
		else{
			for(int m=1;m<n;m*=2){
				int w = 1;
				for(int s=0,k=0; s<n; s += 2*m){
					for(int i=s, j=s+m ; i < s+m; ++i, ++j) {
						int x = a[i], y = a[j];
						a[j] = (x>=y?x-y:x+md-y);
						a[j] = mul(a[j], w);
						a[i] = (x+y>=md?x+y-md:x+y);
					}
					w = mul(w, idw[__builtin_ctz(++k)]);
				}
			}
		}
	}
	vector<int> multiply(vector<int> a, vector<int> b, int eq = 0) {
		int need = a.size() + b.size() - 1;
		int nbase = 0;
		while ((1 << nbase) < need) nbase++;
		int sz = 1 << nbase;
		a.resize(sz);
		b.resize(sz);
		fft(a, 0);
		if (eq) b = a; else fft(b, 0);
		int inv_sz = inv(sz);
		for (int i = 0; i < sz; i++) {
			a[i] = mul(mul(a[i], b[i]), inv_sz);
		}
		fft(a, 1);
		a.resize(need);
		return a;
	}
	vector<int> square(vector<int> a) {
		return multiply(a, a, 1);
	}
};
ll ans[200005];
vector<int>sum[200005], id[200005];
vector<ll>pool[200005];
void dfs3(int v, int u, int root){
	pool[root][dep[v]-dep[root]] += ans[v];
	for(const auto at:edge[v]){
		if(at == u) continue;
		dfs3(at, v, root);
	}
}
void dfs4(int v, int u, int root){
	sum[root][dep[v]-dep[root]] += a[v];
	if(sum[root][dep[v]-dep[root]] >= mod) sum[root][dep[v]-dep[root]] -= mod;
	for(const auto at:edge[v]){
		if(at == u) continue;
		dfs4(at, v, root);
	}
}
void solve(int v, int u){
	for(const auto at:edge[v]){
		if(at == u) continue;
		solve(at, v);
		if(cmp[v] != cmp[at]){
			dfs3(at, v, cmp[v]);
		}
	}
	if(num[v] == 0){
		assert(cmp[v] == v);
		dfs4(v, u, cmp[v]);
		ntt<998244353>kaede;
		vector<int>coef; ll pre = 1;
		for(int i=0;i<sum[cmp[v]].size();i++){
			coef.pb((int)(pre));
			pre = pre * rui[i+1] % mod;
		}
		reverse(all(sum[cmp[v]]));
		auto c = kaede.multiply(sum[cmp[v]], coef);
		for(int i=0;i<id[v].size();i++){
			int V = id[v][i];
			int pt = dep[V]-dep[v];
			ans[V] = c[maxdep[v]-dep[V]] - (pool[v][pt]%mod);
		}
	}
}
void solve(){
	cin>>n>>m;
	rep(i, n) cin >> a[i];
	rep(i, n-1){
		int u, v; cin >>u >> v;
		edge[u].pb(v);
		edge[v].pb(u);
	}
	make();
	rui[0] = 1;
	dfs(0, -1);
	for(int i=1;i<=n;i++) rui[i] = (m-1+i) % mod * modpow(i, mod-2) % mod;
	cmp[0] = 0, num[0] = 0;
	dfs2(0, -1, 0);
	rep(i, n) chmax(len[cmp[i]], num[i]+1);
	rep(i, n){
		if(len[i] == 0) continue;
		assert(num[i] == 0);
		//cout<<i<<" "<<maxdep[i]<<" "<<dep[i]<<endl;
		sum[i].resize(maxdep[i]-dep[i]+1, 0);
		id[i].resize(len[i], 0);
		pool[i].resize(maxdep[i]-dep[i]+1, 0LL);
	}
	rep(i, n) id[cmp[i]][num[i]] = i;
	solve(0, -1);
	rep(i, n) cout << (ans[i]%mod+mod)%mod << (i==n-1?'\n':' ');
	return;
}
int main(){
	ios::sync_with_stdio(0);
	solve();
}
accuracy: 1
time_ms: 820
memory_kb: 68056
final_rank: 10

code_snippet: #pragma region Macros
#pragma GCC optimize("O3")
#pragma GCC target("avx2,avx")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
string YES[2] = {"NO", "YES"};
string Yes[2] = {"No", "Yes"};
string yes[2] = {"no", "yes"};
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return move(res);
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return move(res);
}

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto &e : v) cout << e << " ";
    cout << endl;
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    cout << "(" << p.fi << ", " << p.se << ")";
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
template <class A> string to_string(A v) {
    if(v.empty()) return "{}";
    string ret = "{";
    for(auto &x : v) ret += to_string(x) + ",";
    ret.back() = '}';
    return ret;
}

void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#define endl '\n'
#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
#define debug(x)
#endif
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
// ll rndll(ll n) { return uniform_int_distribution<ll>(0, n - 1)(rng); }

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#pragma endregion

namespace modular {
constexpr ll MOD = 998244353;
const int MAXN = 1100000;
template <ll Modulus> class modint {
    using u64 = ll;

  public:
    u64 a;

    constexpr modint(const u64 x = 0) noexcept : a(((x % Modulus) + Modulus) % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept { return modint(*this) += rhs; }
    constexpr modint operator-(const modint rhs) const noexcept { return modint(*this) -= rhs; }
    constexpr modint operator*(const modint rhs) const noexcept { return modint(*this) *= rhs; }
    template <typename T> constexpr modint operator^(T rhs) const noexcept { return modint(*this) ^= rhs; }
    constexpr modint operator-() const noexcept { return modint() - *this; }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if(a >= Modulus) { a -= Modulus; }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if(a < rhs.a) { a += Modulus; }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr bool operator==(const modint rhs) const noexcept { return a == rhs.a; }
    template <typename T> constexpr modint &operator^=(T n) noexcept {
        modint<Modulus> res = 1;
        modint<Modulus> x = a;
        while(n) {
            if(n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        a = res.a;
        return *this;
    }
};
#define mint modint<MOD>
#define vmint vector<mint>
vmint Inv{0, 1}, Prd{1, 1}, Invprd{1, 1};
mint inv(int n) {
    if(n > MAXN) return mint(n) ^ (MOD - 2);
    if(Inv.size() > n)
        return Inv[n];
    else {
        for(int i = Inv.size(); i <= n; ++i) Inv.emplace_back(Inv[MOD % i] * (-MOD / i));
        return Inv[n];
    }
}
mint inv(mint x) { return inv(x.a); }
mint prd(int n) {
    if(Prd.size() > n)
        return Prd[n];
    else
        for(int i = Prd.size(); i <= n; ++i) Prd.emplace_back(Prd[i - 1] * i);
    return Prd[n];
}
mint invprd(int n) {
    if(Invprd.size() > n)
        return Invprd[n];
    else
        for(int i = Invprd.size(); i <= n; ++i) Invprd.emplace_back(Invprd[i - 1] * inv(i));
    return Invprd[n];
}
mint modpow(ll a, ll n) {
    mint x = a;
    return x ^= n;
}
mint operator/(mint l, mint r) { return l * inv(r); }
mint &operator/=(mint &l, mint r) { return l = l / r; }
mint C(int a, int b) {
    if(a < 0 || b < 0) return 0;
    if(a < b) return 0;
    return prd(a) * invprd(b) * invprd(a - b);
}
mint P(int a, int b) {
    if(a < 0 || b < 0) return 0;
    if(a < b) return 0;
    return prd(a) * invprd(a - b);
}
ostream &operator<<(ostream &os, mint a) {
    os << a.a;
    return os;
}
ostream &operator<<(ostream &os, vmint a) {
    for(auto &e : a) os << e << " ";
    return os;
}
mint operator*(ll x, mint y) { return y * x; }
istream &operator>>(istream &is, mint &a) {
    ll x;
    is >> x;
    a = x;
    return is;
}
mint proot = 3;

void FMT(vmint &f, const bool is_inv = false) {
    const int n = f.size();
    const mint root = is_inv ? inv(proot) : proot;
    vmint g(n);
    for(int b = n >> 1; b > 0; b >>= 1) {
        mint a = root ^ ((MOD - 1) / (n / b)), p = 1;
        for(int i = 0; i < n; i += b << 1) {
            rep(j, b) {
                f[i + j + b] *= p;
                g[(i >> 1) + j] = f[i + j] + f[i + b + j];
                g[(n >> 1) + (i >> 1) + j] = f[i + j] - f[i + b + j];
            }
            p *= a;
        }
        swap(f, g);
    }
    if(is_inv) rep(i, n) f[i] *= inv(n);
}

vmint mul(vmint x, const vmint &y) {
    int n = x.size() + y.size() - 1;
    int s = 1;
    while(s < n) s <<= 1;
    x.resize(s);
    FMT(x);
    vmint z(s);
    rep(i, y.size()) z[i] = y[i];
    FMT(z);
    rep(i, s) x[i] *= z[i];
    FMT(x, true);
    x.resize(n);
    return x;
}

using Poly = vmint;
Poly operator-(Poly f) {
    for(auto &&e : f) e = -e;
    return f;
}
Poly &operator+=(Poly &l, const Poly &r) {
    l.resize(max(l.size(), r.size()));
    rep(i, r.size()) l[i] += r[i];
    return l;
}
Poly operator+(Poly l, const Poly &r) { return l += r; }
Poly &operator-=(Poly &l, const Poly &r) {
    l.resize(max(l.size(), r.size()));
    rep(i, r.size()) l[i] -= r[i];
    return l;
}
Poly operator-(Poly l, const Poly &r) { return l -= r; }
Poly &operator<<=(Poly &f, size_t n) { return f.insert(f.begin(), n, 0), f; }
Poly operator<<(Poly f, size_t n) { return f <<= n; }
Poly &operator>>=(Poly &f, size_t n) { return f.erase(f.begin(), f.begin() + min(f.size(), n)), f; }
Poly operator>>(Poly f, size_t n) { return f >>= n; }
Poly operator*(const Poly &l, const Poly &r) { return mul(l, r); }
Poly &operator*=(Poly &l, const Poly &r) { return l = l * r; }
Poly inv(const Poly &f) {
    Poly g{1 / f[0]};
    while(g.size() < f.size()) {
        Poly x(f.begin(), f.begin() + min(f.size(), g.size() << 1)), y = g;
        x.resize(g.size() << 1), FMT(x);
        y.resize(g.size() << 1), FMT(y);
        rep(i, x.size()) x[i] *= y[i];
        FMT(x, true);
        x >>= g.size();
        x.resize(g.size() << 1), FMT(x);
        rep(i, x.size()) x[i] *= -y[i];
        FMT(x, true);
        g.insert(g.end(), x.begin(), x.begin() + g.size());
    }
    return Poly{begin(g), begin(g) + f.size()};
}
Poly integ(const Poly &f) {
    Poly res(f.size() + 1);
    for(int i = 1; i < (int)res.size(); ++i) res[i] = f[i - 1] / i;
    return res;
}
Poly deriv(const Poly &f) {
    if(f.size() == 0) return Poly();
    Poly res(f.size() - 1);
    rep(i, res.size()) res[i] = f[i + 1] * (i + 1);
    return res;
}
Poly log(const Poly &f) {
    Poly g = integ(inv(f) * deriv(f));
    return Poly{g.begin(), g.begin() + f.size()};
}
Poly exp(const Poly &f) {
    Poly g{1};
    while(g.size() < f.size()) {
        Poly x(f.begin(), f.begin() + min(f.size(), g.size() * 2));
        x[0] += 1;
        g.resize(2 * g.size());
        x -= log(g);
        x *= {g.begin(), g.begin() + g.size() / 2};
        rep2(i, g.size() / 2, min<int>(x.size(), g.size()) - 1) g[i] = x[i];
    }
    return {g.begin(), g.begin() + f.size()};
}

} // namespace modular
using namespace modular;

int main() {
    INT(n, m);
    VEC(int, a, n);
    Graph g(n);
    rep(i, n - 1) {
        INT(u, v);
        g[u].eb(v), g[v].eb(u);
    }
    vi sub(n);
    vmint ans(n);
    vmint binom(n + 1);
    binom[0] = 1;
    rep2(i, 1, n) { binom[i] = binom[i - 1] * ((m - 1) + i) * inv(i); }
    vv(int, v, n);
    vv(mint, dp, n);
    auto dfs = [&](auto &&f, int x, int p) -> void {
        for(auto e : g[x]) {
            if(e != p) {
                f(f, e, x);
                if(si(v[e]) > si(v[x])) swap(v[e], v[x]), swap(dp[e], dp[x]);
                int a = si(v[x]), b = si(v[e]);
                if(!b) continue;
                vmint G(b + 1);
                rep(i, b + 1) G[i] = binom[i];
                auto F = dp[e] * G;
                rep(i, b) ans[v[e][i]] += F[i];
                int d = a - b;
                rep(i, b) ans[v[x][i + d]] -= F[i];
                rep(i, b) dp[x][i + d] += dp[e][i];
                // cout << ans << endl;
            }
        }
        v[x].eb(x), dp[x].eb(a[x]);
    };
    dfs(dfs, 0, -1);
    int k = si(v[0]);
    vmint G(k);
    rep(i, k) G[i] = binom[i];
    auto F = dp[0] * G;
    rep(i, k) ans[v[0][i]] += F[i];
    rep(i, n) {
        if(i) cout << " ";
        cout << ans[i];
    }
    cout << endl;
}
accuracy: 1
time_ms: 170
memory_kb: 49916
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
//const ll MOD=1000000007;
const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}


template<long long int mod=1000000007>
struct Mod_Int{
    typedef long long int ll;
    typedef pair<ll,ll> pll;
    typedef Mod_Int<mod> M;
    ll a;
    
    ll mod_pow(ll a,ll x){
        a%=mod;
        ll ans=1;
        for(int i=0;i<63;i++){
            if(x>>i&1){ans*=a; ans%=mod;}
            a*=a;
            a%=mod;
        }
        return ans;
    }
    
    pll Ex_gcd(ll a,ll b){
        if(b==0){return {1,0};}
        pll ret=Ex_gcd(b,a%b);
        ret.F-=a/b*ret.S;
        return {ret.S,ret.F};
    }
    
    ll prime_R(ll a){
        return mod_pow(a,mod-2);
    }
    
    ll R(ll a){
        ll ret=Ex_gcd(a,mod).F;
        ret%=mod;
        if(ret<0){ret+=mod;}
        return ret;
    }
    
    Mod_Int(ll A=1):a(A){
        a%=mod;
        if(a<0){a+=mod;}
    }
    
    Mod_Int(const M &b):a(b.a){}
    
    M & operator += (const M &b){
        a+=b.a;
        if(a>=mod){a-=mod;}
        return *this;
    }
    
    M operator + (const M &b) const {
        M c=*this;
        return c+=b;
    }
    
    M & operator -= (const M &b){
        a-=b.a;
        if(a<0){a+=mod;}
        return *this;
    }
    
    M operator - (const M &b) const {
        M c=*this;
        return c-=b;
    }
    
    M & operator *= (const M &b){
        (a*=b.a)%=mod;
        return *this;
    }
    
    M operator * (const M &b) const {
        M c=*this;
        return c*=b;
    }
    
    M & operator /= (const M &b){
        (a*=R(b.a))%=mod;
        return *this;
    }
    
    M operator / (const M &b) const {
        M c=*this;
        return c/=b;
    }
    
    M & mod_pow_equal(ll x){
        ll ans=1;
        while(x>0){
            if(x&1){ans*=a; ans%=mod;}
            a*=a;
            a%=mod;
            x>>=1;
        }
        a=ans;
        return *this;
    }
    
    M mod_pow(ll x) const {
        M c(a);
        return c.mod_pow_equal(x);
    }
    
    bool operator == (const M &b) const {return a==b.a;}
    
    bool operator != (const M &b) const {return a!=b.a;}
    
    bool operator <= (const M &b) const {return a<=b.a;}
    
    bool operator < (const M &b) const {return a<b.a;}
    
    bool operator > (const M &b) const {return a>b.a;}
    
    bool operator >= (const M &b) const {return a>=b.a;}
    
    M & operator = (const M &b){
        a=b.a;
        return *this;
    }
    
    M & operator = (const ll &b){
        (a=b)%=mod;
        if(a<0){a+=mod;}
        return *this;
    }
};

template<long long MOD>istream & operator >> (istream &i,Mod_Int<MOD> &A){ll a; cin>>a; A=Mod_Int<MOD>(a); return i;}
template<long long MOD>ostream & operator << (ostream &i,const Mod_Int<MOD> &A){i<<A.a; return i;}

namespace Convolution{
    template<typename T>
    vector<T> fourier(const vector<T> &A,int n,T r){
        vector<T> ret=A;
        vector<T> E(1<<n,1);
        for(int i=1;i<1<<n;i++){E[i]=E[i-1]*r;}
        for(int i=0,j=1;j<1<<n;j++){
            for(int k=1<<(n-1);k>(i^=k);k>>=1);
            if(i>j){swap(ret[i],ret[j]);}
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<1<<n;j+=2<<i){
                for(int k=0;k<1<<i;k++){
                    T P=ret[j|k],Q=ret[j|1<<i|k]*E[(1<<n-i-1)*k];
                    ret[j|k]=P+Q;
                    ret[j|1<<i|k]=P-Q;
                }
            }
        }
        return ret;
    }
};

using namespace Convolution;

using Int=Mod_Int<MOD>;

const Int r=3;
const Int inv=Int(1)/3;
const int MAX=21;
vector<vector<Int>> K;

void make_k(ll M){
  K.resize(MAX+1);
  for(int i=1;i<=MAX;i++){
    K[i].resize(1<<i,0);
    K[i][0]=1;
    for(int j=1;j<1<<(i-1);j++){
      K[i][j]=K[i][j-1]*(M+j-1)/j;
    }
    K[i]=fourier(K[i],i,r.mod_pow(998244352>>i));
  }
}

void cul(vector<Int> &a){
  int sz=a.size();
  int n=0;
  while(sz>(1<<n)){n++;}
  n++;
  a.resize(1<<n,0);
  a=fourier(a,n,r.mod_pow(998244352>>n));
  for(int i=0;i<1<<n;i++){a[i]*=K[n][i];}
  a=fourier(a,n,inv.mod_pow(998244352>>n));
  for(auto &I:a){I/=1<<n;}
  a.resize(sz);
}

ll N,M;
vector<Int> ans;
vector<Int> A;
vector<vector<int>> dp;
vector<vector<int>> edge;


void dfs(int u,int p){
  int mx=0,idx=-1;
  for(auto &v:edge[u]){
    if(v!=p){
      dfs(v,u);
      if(mx<(int)dp[v].size()){
        mx=dp[v].size();
        idx=v;
      }
    }
  }
  if(idx!=-1){swap(dp[u],dp[idx]);}
  int tp=dp[u].size();
  for(auto &v:edge[u]){
    if(v!=p && v!=idx){
      int sz=dp[v].size();
      int dif=tp-sz;
      vector<Int> k(sz);
      for(int i=0;i<sz;i++){k[i]=A[dp[v][i]];}
      cul(k);
      for(int i=0;i<sz;i++){
        ans[dp[v][i]]+=k[i];
        ans[dp[u][dif+i]]-=k[i];
        A[dp[u][dif+i]]+=A[dp[v][i]];
      }
      dp[v].clear();
    }
  }
  dp[u].push_back(u);
}

void solve(){
  dfs(0,-1);
  int sz=dp[0].size();
  vector<Int> k(sz);
  for(int i=0;i<sz;i++){k[i]=A[dp[0][i]];}
  cul(k);
  for(int i=0;i<sz;i++){ans[dp[0][i]]+=k[i];}
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin>>N>>M;
  make_k(M);
  ans.resize(N,0);
  A.resize(N);
  dp.resize(N);
  edge.resize(N);
  cin>>A;
  for(int i=1;i<N;i++){
    int u,v;
    cin>>u>>v;
    edge[u].push_back(v);
    edge[v].push_back(u);
  }
  solve();
  cout<<ans<<endl;
  
  return 0;
}
accuracy: 1
time_ms: 610
memory_kb: 68900
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}


constexpr int bmds(int x){
  const int v[] = {1012924417, 924844033, 998244353,
                   897581057, 645922817};
  return v[x];
}
constexpr int brts(int x){
  const int v[] = {5, 5, 3, 3, 3};
  return v[x];
}

template<int X>
struct NTT{
  static constexpr int md = bmds(X);
  static constexpr int rt = brts(X);
  using M = Mint<int, md>;
  vector< vector<M> > rts,rrts;

  void ensure_base(int n){
    if((int)rts.size()>=n) return;
    rts.resize(n);rrts.resize(n);
    for(int i=1;i<n;i<<=1){
      if(!rts[i].empty()) continue;
      M w=M(rt).pow((md-1)/(i<<1));
      M rw=w.inv();
      rts[i].resize(i);rrts[i].resize(i);
      rts[i][0]=M(1);rrts[i][0]=M(1);
      for(int k=1;k<i;k++){
        rts[i][k]=rts[i][k-1]*w;
        rrts[i][k]=rrts[i][k-1]*rw;
      }
    }
  }

  void ntt(vector<M> &as,bool f){
    int n=as.size();
    assert((n&(n-1))==0);
    ensure_base(n);

    for(int i=0,j=1;j+1<n;j++){
      for(int k=n>>1;k>(i^=k);k>>=1);
      if(i>j) swap(as[i],as[j]);
    }

    for(int i=1;i<n;i<<=1){
      for(int j=0;j<n;j+=i*2){
        for(int k=0;k<i;k++){
          M z=as[i+j+k]*(f?rrts[i][k]:rts[i][k]);
          as[i+j+k]=as[j+k]-z;
          as[j+k]+=z;
        }
      }
    }

    if(f){
      M tmp=M(n).inv();
      for(int i=0;i<n;i++) as[i]*=tmp;
    }
  }

  vector<M> multiply(vector<M> as,vector<M> bs){
    int need=as.size()+bs.size()-1;
    int sz=1;
    while(sz<need) sz<<=1;
    as.resize(sz,M(0));
    bs.resize(sz,M(0));

    ntt(as,0);ntt(bs,0);
    for(int i=0;i<sz;i++) as[i]*=bs[i];
    ntt(as,1);

    as.resize(need);
    return as;
  }

  vector<int> multiply(vector<int> as,vector<int> bs){
    vector<M> am(as.size()),bm(bs.size());
    for(int i=0;i<(int)am.size();i++) am[i]=M(as[i]);
    for(int i=0;i<(int)bm.size();i++) bm[i]=M(bs[i]);
    vector<M> cm=multiply(am,bm);
    vector<int> cs(cm.size());
    for(int i=0;i<(int)cs.size();i++) cs[i]=cm[i].v;
    return cs;
  }
};
template<int X> constexpr int NTT<X>::md;
template<int X> constexpr int NTT<X>::rt;


template<typename T>
struct FormalPowerSeries{
  using Poly = vector<T>;
  using Conv = function<Poly(Poly, Poly)>;
  Conv conv;
  FormalPowerSeries(Conv conv):conv(conv){}

  Poly pre(const Poly &as,int deg){
    return Poly(as.begin(),as.begin()+min((int)as.size(),deg));
  }

  Poly add(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,T(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]+=bs[i];
    return cs;
  }

  Poly sub(Poly as,Poly bs){
    int sz=max(as.size(),bs.size());
    Poly cs(sz,T(0));
    for(int i=0;i<(int)as.size();i++) cs[i]+=as[i];
    for(int i=0;i<(int)bs.size();i++) cs[i]-=bs[i];
    return cs;
  }

  Poly mul(Poly as,Poly bs){
    return conv(as,bs);
  }

  Poly mul(Poly as,T k){
    for(auto &a:as) a*=k;
    return as;
  }

  // F(0) must not be 0
  Poly inv(Poly as,int deg){
    assert(as[0]!=T(0));
    Poly rs({T(1)/as[0]});
    for(int i=1;i<deg;i<<=1)
      rs=pre(sub(add(rs,rs),mul(mul(rs,rs),pre(as,i<<1))),i<<1);
    return rs;
  }

  // not zero
  Poly div(Poly as,Poly bs){
    while(as.back()==T(0)) as.pop_back();
    while(bs.back()==T(0)) bs.pop_back();
    if(bs.size()>as.size()) return Poly();
    reverse(as.begin(),as.end());
    reverse(bs.begin(),bs.end());
    int need=as.size()-bs.size()+1;
    Poly ds=pre(mul(as,inv(bs,need)),need);
    reverse(ds.begin(),ds.end());
    return ds;
  }

  Poly mod(Poly as,Poly bs){
    if(as==Poly(as.size(),0)) return Poly({0});
    as=sub(as,mul(div(as,bs),bs));
    if(as==Poly(as.size(),0)) return Poly({0});
    while(as.back()==T(0)) as.pop_back();
    return as;
  }

  // F(0) must be 1
  Poly sqrt(Poly as,int deg){
    assert(as[0]==T(1));
    T inv2=T(1)/T(2);
    Poly ss({T(1)});
    for(int i=1;i<deg;i<<=1){
      ss=pre(add(ss,mul(pre(as,i<<1),inv(ss,i<<1))),i<<1);
      for(T &x:ss) x*=inv2;
    }
    return ss;
  }

  Poly diff(Poly as){
    int n=as.size();
    Poly rs(n-1);
    for(int i=1;i<n;i++) rs[i-1]=as[i]*T(i);
    return rs;
  }

  Poly integral(Poly as){
    int n=as.size();
    Poly rs(n+1);
    rs[0]=T(0);
    for(int i=0;i<n;i++) rs[i+1]=as[i]/T(i+1);
    return rs;
  }

  // F(0) must be 1
  Poly log(Poly as,int deg){
    return pre(integral(mul(diff(as),inv(as,deg))),deg);
  }

  // F(0) must be 0
  Poly exp(Poly as,int deg){
    Poly f({T(1)});
    as[0]+=T(1);
    for(int i=1;i<deg;i<<=1)
      f=pre(mul(f,sub(pre(as,i<<1),log(f,i<<1))),i<<1);
    return f;
  }

  Poly partition(int n){
    Poly rs(n+1);
    rs[0]=T(1);
    for(int k=1;k<=n;k++){
      if(1LL*k*(3*k+1)/2<=n) rs[k*(3*k+1)/2]+=T(k%2?-1LL:1LL);
      if(1LL*k*(3*k-1)/2<=n) rs[k*(3*k-1)/2]+=T(k%2?-1LL:1LL);
    }
    return inv(rs,n+1);
  }

  Poly bernoulli(int n){
    Poly rs(n+1,1);
    for(int i=1;i<=n;i++) rs[i]=rs[i-1]/T(i+1);
    rs=inv(rs,n+1);
    T tmp(1);
    for(int i=1;i<=n;i++){
      tmp*=T(i);
      rs[i]*=tmp;
    }
    return rs;
  }
};


struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;


struct Centroid{
  vector<int> sz,dead;
  vector< vector<int> > G;
  Centroid(){}
  Centroid(int n):sz(n,1),dead(n,0),G(n){}

  void add_edge(int u,int v){
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  int dfs(int v,int p){
    sz[v]=1;
    for(int u:G[v])
      if(u!=p&&!dead[u]) sz[v]+=dfs(u,v);
    return sz[v];
  }

  void find(int v,int p,int tmp,vector<int> &cs) {
    int ok=1;
    for (int u:G[v]){
      if(u==p||dead[u]) continue;
      find(u,v,tmp,cs);
      ok&=(sz[u]<=tmp/2);
    }
    ok&=(tmp-sz[v]<=tmp/2);
    if(ok) cs.push_back(v);
  }

  vector<int> build(int r) {
    int tmp=dfs(r,-1);
    vector<int> cs;
    find(r,-1,tmp,cs);
    return cs;
  }

  void disable(int v){
    dead[v]=1;
  }

  void enable(int v){
    dead[v]=0;
  }

  int alive(int v){
    return !dead[v];
  }
};


template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}

//INSERT ABOVE HERE
signed main(){
  NTT<2> ntt;
  using M = decltype(ntt)::M;
  auto conv=[&](auto as,auto bs){return ntt.multiply(as,bs);};
  FormalPowerSeries<M> FPS(conv);
  using Poly = decltype(FPS)::Poly;

  int n,m;
  cin>>n>>m;

  Poly as(n);
  for(int i=0;i<n;i++) cin>>as[i].v;

  Centroid G(n+1);
  G.add_edge(n,0);
  for(int i=1;i<n;i++){
    int u,v;
    cin>>u>>v;
    G.add_edge(u,v);
  }

  vector<int> par(n+1,-1);
  {
    queue<int> que;
    que.emplace(n);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int u:G.G[v]){
        if(u==par[v]) continue;
        par[u]=v;
        que.emplace(u);
      }
    }
  }

  vector<int> dead(n+1,0);
  auto disable=
    [&](int k){
      dead[k]=1;
      G.disable(k);
    };
  disable(n);

  const int deg = 1<<18;
  Poly ps(n,M(1));
  ps=FPS.exp(FPS.mul(FPS.log(ps,deg),M(m)),deg);

  queue<int> que;
  que.emplace(G.build(0)[0]);

  Poly ans(n);
  while(!que.empty()){
    int r=que.front();que.pop();

    Poly qs;
    MFP([&](auto dfs,int v,int p,int h)->void{
          while(!(h<(int)qs.size())) qs.emplace_back(0);
          qs[h]+=as[v];
          for(int u:G.G[v]){
            if(u==p) continue;
            if(dead[u]) continue;
            dfs(u,v,h+1);
          }
        })(r,par[r],0);
    reverse(qs.begin(),qs.end());

    vector<int> bs;
    int p=r;
    while(~p&&!dead[p]){
      bs.emplace_back(p);
      p=par[p];
    }

    int len=qs.size()-1;
    qs.resize(len+bs.size(),M(0));
    auto rs=FPS.mul(FPS.pre(ps,qs.size()),qs);

    for(int i=0;i<(int)bs.size();i++) ans[bs[i]]+=rs[len+i];

    disable(r);
    for(int u:G.G[r])
      if(!dead[u]) que.emplace(G.build(u)[0]);
  }

  for(int i=0;i<n;i++){
    if(i) cout<<" ";
    cout<<ans[i];
  }
  cout<<endl;
  return 0;
}
accuracy: 1
time_ms: 1340
memory_kb: 67068
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
//const ll MOD=1000000007;
const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}


template<long long int mod=1000000007>
struct Mod_Int{
    typedef long long int ll;
    typedef pair<ll,ll> pll;
    typedef Mod_Int<mod> M;
    ll a;
    
    ll mod_pow(ll a,ll x){
        a%=mod;
        ll ans=1;
        for(int i=0;i<63;i++){
            if(x>>i&1){ans*=a; ans%=mod;}
            a*=a;
            a%=mod;
        }
        return ans;
    }
    
    pll Ex_gcd(ll a,ll b){
        if(b==0){return {1,0};}
        pll ret=Ex_gcd(b,a%b);
        ret.F-=a/b*ret.S;
        return {ret.S,ret.F};
    }
    
    ll prime_R(ll a){
        return mod_pow(a,mod-2);
    }
    
    ll R(ll a){
        ll ret=Ex_gcd(a,mod).F;
        ret%=mod;
        if(ret<0){ret+=mod;}
        return ret;
    }
    
    Mod_Int(ll A=1):a(A){
        a%=mod;
        if(a<0){a+=mod;}
    }
    
    Mod_Int(const M &b):a(b.a){}
    
    M & operator += (const M &b){
        a+=b.a;
        if(a>=mod){a-=mod;}
        return *this;
    }
    
    M operator + (const M &b) const {
        M c=*this;
        return c+=b;
    }
    
    M & operator -= (const M &b){
        a-=b.a;
        if(a<0){a+=mod;}
        return *this;
    }
    
    M operator - (const M &b) const {
        M c=*this;
        return c-=b;
    }
    
    M & operator *= (const M &b){
        (a*=b.a)%=mod;
        return *this;
    }
    
    M operator * (const M &b) const {
        M c=*this;
        return c*=b;
    }
    
    M & operator /= (const M &b){
        (a*=R(b.a))%=mod;
        return *this;
    }
    
    M operator / (const M &b) const {
        M c=*this;
        return c/=b;
    }
    
    M & mod_pow_equal(ll x){
        ll ans=1;
        while(x>0){
            if(x&1){ans*=a; ans%=mod;}
            a*=a;
            a%=mod;
            x>>=1;
        }
        a=ans;
        return *this;
    }
    
    M mod_pow(ll x) const {
        M c(a);
        return c.mod_pow_equal(x);
    }
    
    bool operator == (const M &b) const {return a==b.a;}
    
    bool operator != (const M &b) const {return a!=b.a;}
    
    bool operator <= (const M &b) const {return a<=b.a;}
    
    bool operator < (const M &b) const {return a<b.a;}
    
    bool operator > (const M &b) const {return a>b.a;}
    
    bool operator >= (const M &b) const {return a>=b.a;}
    
    M & operator = (const M &b){
        a=b.a;
        return *this;
    }
    
    M & operator = (const ll &b){
        (a=b)%=mod;
        if(a<0){a+=mod;}
        return *this;
    }
};

template<long long MOD>istream & operator >> (istream &i,Mod_Int<MOD> &A){ll a; cin>>a; A=Mod_Int<MOD>(a); return i;}
template<long long MOD>ostream & operator << (ostream &i,const Mod_Int<MOD> &A){i<<A.a; return i;}

namespace Convolution{
    template<typename T>
    vector<T> fourier(const vector<T> &A,int n,T r){
        vector<T> ret=A;
        vector<T> E(1<<n,1);
        for(int i=1;i<1<<n;i++){E[i]=E[i-1]*r;}
        for(int i=0,j=1;j<1<<n;j++){
            for(int k=1<<(n-1);k>(i^=k);k>>=1);
            if(i>j){swap(ret[i],ret[j]);}
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<1<<n;j+=2<<i){
                for(int k=0;k<1<<i;k++){
                    T P=ret[j|k],Q=ret[j|1<<i|k]*E[(1<<n-i-1)*k];
                    ret[j|k]=P+Q;
                    ret[j|1<<i|k]=P-Q;
                }
            }
        }
        return ret;
    }
};

using namespace Convolution;

using Int=Mod_Int<MOD>;

const Int r=3;
const Int inv=Int(1)/3;
const int MAX=21;
vector<vector<Int>> K;

void make_k(ll M){
  K.resize(MAX+1);
  for(int i=1;i<=MAX;i++){
    K[i].resize(1<<i,0);
    K[i][0]=1;
    for(int j=1;j<1<<(i-1);j++){
      K[i][j]=K[i][j-1]*(M+j-1)/j;
    }
    K[i]=fourier(K[i],i,r.mod_pow(998244352>>i));
  }
}

void cul(vector<Int> &a){
  int sz=a.size();
  int n=0;
  while(sz>(1<<n)){n++;}
  n++;
  a.resize(1<<n,0);
  a=fourier(a,n,r.mod_pow(998244352>>n));
  for(int i=0;i<1<<n;i++){a[i]*=K[n][i];}
  a=fourier(a,n,inv.mod_pow(998244352>>n));
  for(auto &I:a){I/=1<<n;}
  a.resize(sz);
}

ll N,M;
vector<Int> ans;
vector<Int> A;
vector<vector<int>> dp;
vector<vector<int>> edge;


void dfs(int u,int p){
  int mx=0,idx=-1;
  for(auto &v:edge[u]){
    if(v!=p){
      dfs(v,u);
      if(mx<(int)dp[v].size()){
        mx=dp[v].size();
        idx=v;
      }
    }
  }
  if(idx!=-1){swap(dp[u],dp[idx]);}
  int tp=dp[u].size();
  for(auto &v:edge[u]){
    if(v!=p && v!=idx){
      int sz=dp[v].size();
      int dif=tp-sz;
      vector<Int> k(sz);
      for(int i=0;i<sz;i++){k[i]=A[dp[v][i]];}
      cul(k);
      for(int i=0;i<sz;i++){
        ans[dp[v][i]]+=k[i];
        ans[dp[u][dif+i]]-=k[i];
        A[dp[u][dif+i]]+=A[dp[v][i]];
      }
      dp[v].clear();
    }
  }
  dp[u].push_back(u);
}

void solve(){
  dfs(0,-1);
  int sz=dp[0].size();
  vector<Int> k(sz);
  for(int i=0;i<sz;i++){k[i]=A[dp[0][i]];}
  cul(k);
  for(int i=0;i<sz;i++){ans[dp[0][i]]+=k[i];}
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin>>N>>M;
  make_k(M);
  ans.resize(N,0);
  A.resize(N);
  dp.resize(N);
  edge.resize(N);
  cin>>A;
  for(int i=1;i<N;i++){
    int u,v;
    cin>>u>>v;
    edge[u].push_back(v);
    edge[v].push_back(u);
  }
  solve();
  cout<<ans<<endl;
  
  return 0;
}
accuracy: 1
time_ms: 920
memory_kb: 68776
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}



int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll N,K;
  cin>>N>>K;
  vector<ll> X(N),Y(N);
  for(int i=0;i<N;i++){cin>>X[i]>>Y[i];}
  auto cul1=
    [](const vector<ll> &X){
      ll lf=X[0],rg=X[0],ret=0;
      for(auto &I:X){
        if(lf<=I && I<=rg){lf=I; rg=I;}
        else if(rg<I){ret+=I-rg; lf=rg; rg=I;}
        else{ret+=lf-I; rg=lf; lf=I;}
      }
      return ret;
    };
  auto cul2=
    [](const vector<ll> &X){
      ll ret=0,ls=X[0];
      for(auto &I:X){ret+=abs(I-ls); ls=I;}
      return ret;
    };
  cout<<max(cul1(X)+cul1(Y),cul2(X)+cul2(Y)-K)<<endl;


  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4584
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

//INSERT ABOVE HERE
signed main(){
  Int n,k;
  cin>>n>>k;
  vector<Int> xs(n),ys(n);
  for(Int i=0;i<n;i++) cin>>xs[i]>>ys[i];

  Int ans=0,dif=0;
  auto calc=
    [&](vector<Int> zs){
      for(Int i=0;i+1<n;i++) ans+=abs(zs[i+1]-zs[i]);
      for(Int i=1;i+1<n;i++){
        if(zs[i-1]<zs[i]&&zs[i]>zs[i+1]){
          Int d=zs[i]-max(zs[i-1],zs[i+1]);
          dif+=d;
          zs[i]-=d;
        }
        if(zs[i-1]>zs[i]&&zs[i]<zs[i+1]){
          Int d=min(zs[i-1],zs[i+1])-zs[i];
          dif+=d;
          zs[i]+=d;
        }
      }
    };
  calc(xs);calc(ys);

  chmin(dif,k);
  ans-=dif;
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 5388
final_rank: 2