#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const long long INF = 1e18;
long long N, tot, Size[MAXN], Max[MAXN];
long long Mod, cnt, K, X, w[MAXN];
long long kpow[MAXN] = {1}, kinv[MAXN], df[MAXN], dt[MAXN], target[MAXN];
long long dep[MAXN], List[MAXN], in[MAXN], out[MAXN];
bool vst[MAXN];
vector<long long> Path[MAXN];
vector<long long> a[MAXN];
inline long long GetLL() {
  long long num = 0, bj = 1;
  char c = getchar();
  while (!isdigit(c)) bj = (bj == -1 || c == '-') ? -1 : 1, c = getchar();
  while (isdigit(c)) num = num * 10 + c - '0', c = getchar();
  return num * bj;
}
inline long long Pow(long long a, long long b) {
  long long ret = 1, base = a;
  while (b) {
    if (b & 1) ret = ret * base % Mod;
    base = base * base % Mod;
    b >>= 1;
  }
  return ret;
}
map<long long, long long> from, to;
map<long long, long long>::iterator m_it;
inline void add(map<long long, long long>& h, long long pos, long long val) {
  m_it = h.find(pos);
  if (m_it == h.end())
    h[pos] = val;
  else
    m_it->second += val;
}
inline long long count(map<long long, long long>& h, long long pos) {
  m_it = h.find(pos);
  if (m_it == h.end())
    return 0;
  else
    return m_it->second;
}
void FindCore(long long u, long long fa) {
  Size[u] = 1, Max[u] = 0, List[++tot] = u;
  vector<long long>::iterator it;
  for (it = a[u].begin(); it != a[u].end(); ++it) {
    if (*it == fa || vst[*it]) continue;
    FindCore(*it, u);
    Size[u] += Size[*it];
    Max[u] = max(Max[u], Size[*it]);
  }
}
inline long long GetCore(long long x) {
  tot = 0, FindCore(x, 0);
  long long Min = INF, Core = -1;
  for (register int i = 1; i <= tot; i++) {
    long long u = List[i];
    Max[u] = max(Max[u], Size[x] - Size[u]);
    if (Min > Max[u]) Min = Max[u], Core = u;
  }
  return Core;
}
void NewPath(long long u, long long fa, long long c) {
  Path[c].push_back(u);
  vector<long long>::iterator it;
  for (it = a[u].begin(); it != a[u].end(); ++it) {
    if (*it == fa || vst[*it]) continue;
    NewPath(*it, u, c);
  }
}
void GetDist(long long u, long long fa) {
  vector<long long>::iterator it;
  for (it = a[u].begin(); it != a[u].end(); ++it) {
    if (vst[*it] || *it == fa) continue;
    dep[*it] = dep[u] + 1;
    dt[*it] = (dt[u] + w[*it] * kpow[dep[*it]]) % Mod;
    df[*it] = (df[u] * K + w[*it]) % Mod;
    GetDist(*it, u);
  }
}
void Solve() {
  from.clear(), to.clear();
  for (register int i = 1; i <= tot; i++) {
    long long u = List[i];
    vector<long long>::iterator p;
    for (p = Path[u].begin(); p != Path[u].end(); ++p) add(to, dt[*p], 1);
  }
  for (register int i = 1; i <= tot; i++) {
    long long u = List[i];
    vector<long long>::iterator p;
    for (p = Path[u].begin(); p != Path[u].end(); ++p) add(to, dt[*p], -1);
    for (p = Path[u].begin(); p != Path[u].end(); ++p) {
      in[*p] += count(from, dt[*p]);
      out[*p] += count(to, target[*p]);
    }
    for (p = Path[u].begin(); p != Path[u].end(); ++p) add(from, target[*p], 1);
  }
}
void Divide(long long x) {
  x = GetCore(x);
  df[x] = dt[x] = w[x], vst[x] = 1, dep[x] = 0;
  GetDist(x, 0);
  for (register int i = 1; i <= tot; i++) {
    if (List[i] == x && dt[List[i]] == X)
      in[x]++, out[x]++;
    else {
      if (dt[List[i]] == X) in[List[i]]++, out[x]++;
      if (df[List[i]] == X) in[x]++, out[List[i]]++;
    }
  }
  tot = 0;
  vector<long long>::iterator it;
  for (it = a[x].begin(); it != a[x].end(); ++it) {
    if (vst[*it]) continue;
    Path[*it].clear(), List[++tot] = *it;
    NewPath(*it, 0, *it);
    vector<long long>::iterator p;
    for (p = Path[*it].begin(); p != Path[*it].end(); ++p)
      target[*p] = ((X - df[*p] + Mod) * kinv[dep[*p]] + w[x]) % Mod;
  }
  Solve();
  reverse(List + 1, List + tot + 1);
  Solve();
  for (it = a[x].begin(); it != a[x].end(); ++it) {
    if (vst[*it]) continue;
    Divide(*it);
  }
}
int main() {
  N = GetLL(), Mod = GetLL(), K = GetLL(), X = GetLL() % Mod;
  for (register int i = 1; i <= N; i++) w[i] = GetLL();
  for (register int i = 1; i < N; i++) {
    long long u = GetLL(), v = GetLL();
    a[u].push_back(v);
    a[v].push_back(u);
  }
  for (register int i = 1; i <= N; i++) reverse(a[i].begin(), a[i].end());
  for (register int i = 1; i <= N; i++) {
    kpow[i] = kpow[i - 1] * K % Mod;
    kinv[i] = Pow(kpow[i], Mod - 2);
  }
  Divide(1);
  for (register int i = 1; i <= N; i++)
    cnt += in[i] * (N - out[i]) + out[i] * (N - in[i]) +
           2 * (in[i] * (N - in[i]) + out[i] * (N - out[i]));
  printf("%lld\n", N * N * N - cnt / 2);
  return 0;
}
