#include <bits/stdc++.h>
const long long maxn = 1e5 + 5;
long long n, mod, k, X, invk, val[maxn];
long long mul[maxn], inv[maxn];
long long in0[maxn], out0[maxn];
long long head[maxn], tot;
struct Edge {
  long long next, to;
} e[maxn << 1];
inline void add_edge(long long x, long long y) {
  e[++tot].next = head[x];
  e[tot].to = y, head[x] = tot;
}
inline long long ksm(long long a, long long x) {
  long long ans = 1, base = a;
  while (x) {
    if (x & 1) ans = (long long)ans * base % mod;
    base = (long long)base * base % mod;
    x >>= 1;
  }
  return ans;
}
std ::map<long long, long long> mp1, mp2;
long long vis[maxn], siz[maxn], totsiz, minmax, rt;
inline void getcorsiz(long long u, long long F) {
  siz[u] = 1;
  for (long long i = head[u], v; v = e[i].to, i; i = e[i].next)
    if (v != F && !vis[v]) getcorsiz(v, u), siz[u] += siz[v];
}
inline void getcore(long long u, long long F) {
  siz[u] = 1;
  long long maxson = 0;
  for (long long i = head[u], v; v = e[i].to, i; i = e[i].next)
    if (v != F && !vis[v])
      getcore(v, u), siz[u] += siz[v], maxson = std::max(maxson, siz[v]);
  maxson = std::max(maxson, totsiz - siz[u]);
  if (maxson < minmax) minmax = maxson, rt = u;
}
long long nod[maxn], S[maxn], V[maxn], cnt;
inline void getdis(long long u, long long F, long long dep, long long nowv,
                   long long nows) {
  ++mp1[nows], ++mp2[(long long)(X - nowv + mod) % mod * inv[dep + 1] % mod];
  nod[++cnt] = u;
  S[cnt] = nows,
  V[cnt] = (long long)(X - nowv + mod) % mod * inv[dep + 1] % mod;
  for (long long i = head[u], v; v = e[i].to, i; i = e[i].next) {
    if (vis[v] || v == F) continue;
    getdis(v, u, dep + 1, (long long)(nowv * k % mod + val[v]) % mod,
           (nows + (long long)mul[dep] * val[v] % mod) % mod);
  }
}
inline void getans(long long sign) {
  for (long long i = 1; i <= cnt; ++i) {
    out0[nod[i]] += sign * mp1[V[i]];
    in0[nod[i]] += sign * mp2[S[i]];
  }
}
inline void solve(long long u) {
  mp1.clear(), mp2.clear(), cnt = 0;
  getdis(u, 0, 0, val[u], 0), getans(1);
  for (long long i = head[u], v; v = e[i].to, i; i = e[i].next) {
    if (vis[v]) continue;
    mp1.clear(), mp2.clear(), cnt = 0;
    getdis(v, u, 1, (long long)(k * val[u] % mod + val[v]) % mod, val[v]),
        getans(-1);
  }
  vis[u] = 1;
  for (long long i = head[u], v; v = e[i].to, i; i = e[i].next) {
    if (vis[v]) continue;
    totsiz = siz[v];
    minmax = 0x3f3f3f3f, getcore(v, 0);
    getcorsiz(rt, 0);
    solve(rt);
  }
}
signed main() {
  scanf("%lld %lld %lld %lld", &n, &mod, &k, &X);
  for (long long i = 1; i <= n; ++i) scanf("%lld", &val[i]), val[i] %= mod;
  mul[0] = inv[0] = 1;
  mul[1] = k, invk = inv[1] = ksm(k, mod - 2);
  for (long long i = 2; i <= n; ++i)
    mul[i] = (long long)mul[i - 1] * k % mod, inv[i] = inv[i - 1] * invk % mod;
  for (long long i = 1, x, y; i < n; ++i)
    scanf("%lld %lld", &x, &y), add_edge(x, y), add_edge(y, x);
  totsiz = n;
  minmax = 0x3f3f3f3f, getcore(1, 0);
  getcorsiz(rt, 0);
  solve(rt);
  long long ANS = 0;
  for (long long i = 1; i <= n; ++i)
    ANS += ((long long)(2 * out0[i] * (n - out0[i]) + in0[i] * (n - out0[i]) +
                        out0[i] * (n - in0[i]) + 2 * in0[i] * (n - in0[i])));
  printf("%lld", (long long)n * n * n - ANS / 2);
  return 0;
}
