#include <bits/stdc++.h>
using namespace std;
const int maxn = 100005;
const int maxe = maxn * 2;
const int INF = 0x3f3f3f3fll;
struct edge {
  int to, next;
};
edge elist[maxe];
int head[maxn], etop;
inline void adde(int from, int to) {
  elist[++etop] = (edge){to, head[from]};
  head[from] = etop;
}
int vst[maxn], siz[maxn];
void dfs_siz(int u, int prt) {
  siz[u] = 1;
  for (int p = head[u]; p; p = elist[p].next) {
    int to = elist[p].to;
    if (to == prt || vst[to]) continue;
    dfs_siz(to, u);
    siz[u] += siz[to];
  }
}
int mn, mc, tot;
void find(int u, int prt) {
  int mv = tot - siz[u];
  for (int p = head[u]; p; p = elist[p].next) {
    int to = elist[p].to;
    if (to == prt || vst[to]) continue;
    find(to, u);
    if (siz[to] > mv) mv = siz[to];
  }
  if (mv <= mn) {
    mn = mv;
    mc = u;
  }
}
int N, K, X, Y;
long long qpow(long long a, long long p) {
  long long r = 1;
  for (a %= Y; p; p >>= 1, a = a * a % Y)
    if (p & 1) r = r * a % Y;
  return r;
}
long long inv(long long a) { return qpow(a, Y - 2); }
int dat[maxn], powk[maxn];
struct binary_table {
  int pool[maxn], cnt[maxn], len, npos;
  inline void push(int x) {
    pool[++len] = x;
    cnt[len] = 0;
  }
  void init() {
    sort(pool + 1, pool + len + 1);
    int j = 1;
    for (int i = 1; i <= len; i++) {
      if (pool[i] == pool[j])
        cnt[j]++;
      else {
        pool[++j] = pool[i];
        cnt[j]++;
      }
    }
    len = j;
  }
  inline int& operator[](const int x) {
    int p = lower_bound(pool + 1, pool + len + 1, x) - pool;
    if (1 <= p && p <= len && pool[p] == x) return cnt[p];
    npos = 0;
    return npos;
  }
  inline void clear() { len = 0; }
} M1, M2;
int s1[maxn], s2[maxn], tu[maxn];
void dfs_add(int u, int prt, int d) {
  s1[u] = ((long long)s1[prt] * K % Y + dat[u]) % Y;
  s2[u] = (s2[prt] + (long long)dat[u] * powk[d] % Y) % Y;
  tu[u] = (X - s1[u] + Y) * (long long)inv(powk[d]) % Y;
  M1.push(s2[u]);
  M2.push(tu[u]);
  for (int p = head[u]; p; p = elist[p].next)
    if (elist[p].to != prt && !vst[elist[p].to]) {
      dfs_add(elist[p].to, u, d + 1);
    }
}
void dfs_remove(int u, int prt) {
  M1[s2[u]]--;
  M2[tu[u]]--;
  for (int p = head[u]; p; p = elist[p].next)
    if (elist[p].to != prt && !vst[elist[p].to]) {
      dfs_remove(elist[p].to, u);
    }
}
void dfs_resume(int u, int prt) {
  M1[s2[u]]++;
  M2[tu[u]]++;
  for (int p = head[u]; p; p = elist[p].next)
    if (elist[p].to != prt && !vst[elist[p].to]) {
      dfs_resume(elist[p].to, u);
    }
}
int st[maxn], ed[maxn];
void dfs_solve(int u, int prt) {
  st[u] += M1[tu[u]];
  ed[u] += M2[s2[u]];
  for (int p = head[u]; p; p = elist[p].next)
    if (elist[p].to != prt && !vst[elist[p].to]) {
      dfs_solve(elist[p].to, u);
    }
}
void solve(int u) {
  M1.clear();
  M2.clear();
  tu[u] = X;
  s1[u] = 0;
  s2[u] = dat[u];
  M1.push(s2[u]);
  M2.push(tu[u]);
  for (int p = head[u]; p; p = elist[p].next)
    if (!vst[elist[p].to]) {
      dfs_add(elist[p].to, u, 1);
    }
  M1.init();
  M2.init();
  st[u] += M1[tu[u]];
  ed[u] += M2[s2[u]];
  for (int p = head[u]; p; p = elist[p].next) {
    int to = elist[p].to;
    if (vst[to]) continue;
    dfs_remove(to, u);
    dfs_solve(to, u);
    dfs_resume(to, u);
  }
}
void dfs_main(int u) {
  dfs_siz(u, 0);
  mn = INF;
  mc = 0;
  tot = siz[u];
  find(u, 0);
  u = mc;
  vst[u] = 1;
  solve(u);
  for (int p = head[u]; p; p = elist[p].next)
    if (!vst[elist[p].to]) dfs_main(elist[p].to);
}
int dfs(int u, int prt, int sum, int mul) {
  int ans = 0;
  sum = (sum + (long long)dat[u] * mul % Y) % Y;
  if (sum == X) {
    ed[u]++;
    ans++;
  }
  for (int p = head[u]; p; p = elist[p].next) {
    int to = elist[p].to;
    if (to == prt) continue;
    ans += dfs(to, u, sum, (long long)mul * K % Y);
  }
  return ans;
}
int main() {
  scanf("%d%d%d%d", &N, &Y, &K, &X);
  for (int i = 1; i <= N; i++) {
    scanf("%d", &dat[i]);
    dat[i] %= Y;
  }
  for (int i = 1; i < N; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    adde(a, b);
    adde(b, a);
  }
  powk[0] = 1;
  for (int i = 1; i <= N + 1; i++) powk[i] = (long long)powk[i - 1] * K % Y;
  if (K == Y) {
    int cnt = 0;
    for (int i = 1; i <= N; i++)
      if (dat[i] == X) cnt++;
    for (int i = 1; i <= N; i++) {
      if (dat[i] == X) st[i] += N;
      ed[i] += cnt;
    }
  } else if (N <= 800) {
    for (int i = 1; i <= N; i++) st[i] = dfs(i, 0, 0, 1);
  } else {
    dfs_main(1);
  }
  long long tot = (long long)N * N * N;
  for (int i = 1; i <= N; i++) {
    tot -= (long long)st[i] * N * 3;
    tot += (long long)st[i] * ed[i];
    tot += (long long)st[i] * st[i];
    tot += (long long)ed[i] * ed[i];
  }
  cout << tot << '\n';
  return 0;
}
