#include <bits/stdc++.h>
using namespace std;
inline char getch() {
  static char buf[10000], *p1 = buf, *p2 = buf;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
inline long long read() {
  long long s = 0, f = 1;
  char ch = getch();
  while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getch();
  while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getch();
  return s * f;
}
const int MaxN = 1e5 + 5;
struct Edge {
  int to, nxt;
};
Edge e[MaxN << 1];
int h[MaxN], cnt;
void Link(int x, int y) {
  e[++cnt] = (Edge){y, h[x]};
  h[x] = cnt;
}
int n;
long long p, k, r, val[MaxN];
int in_0[MaxN], in_1[MaxN];
int out_0[MaxN], out_1[MaxN];
int siz[MaxN], rt, mx[MaxN];
int vis[MaxN], N;
long long ksm(long long x, long long y, long long p) {
  long long res = 1;
  x %= p;
  y = (y + p - 1) % (p - 1);
  for (; y; y >>= 1, x = x * x % p)
    if (y & 1) res = res * x % p;
  return res;
}
void getRt(int x, int fa) {
  siz[x] = 1;
  mx[x] = 0;
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (y == fa || vis[y]) continue;
    getRt(y, x);
    siz[x] += siz[y];
    mx[x] = max(mx[x], siz[y]);
  }
  mx[x] = max(mx[x], N - siz[x]);
  if (mx[rt] > mx[x]) rt = x;
}
map<int, int> Map1, Map2;
int F0[MaxN], F1[MaxN];
int G0[MaxN], G1[MaxN];
int dep[MaxN];
long long inv[MaxN], Pow[MaxN];
void Dfs(int x, int fa, int rt) {
  dep[x] = dep[fa] + 1;
  F1[x] = (F1[fa] + 1ll * Pow[dep[x] - 1] * val[x] % p) % p;
  F0[x] = (F1[x] - val[rt] + p) % p;
  G1[x] = (1ll * G1[fa] * k % p + val[x]) % p;
  G0[x] = (G1[x] - 1ll * Pow[dep[x] - 1] * val[rt] % p) % p;
  G0[x] = 1ll * (r - G0[x] + p) % p * inv[dep[x] - 1] % p;
  if (fa) {
    Map1[F0[x]]++;
    Map2[G0[x]]++;
  }
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (y == fa || vis[y]) continue;
    Dfs(y, x, rt);
  }
}
void Dec(int x, int fa) {
  Map1[F0[x]]--;
  Map2[G0[x]]--;
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (y == fa || vis[y]) continue;
    Dec(y, x);
  }
}
void Get(int x, int fa, int rt) {
  out_0[x] += Map1[1ll * (r - G1[x] + p) % p * inv[dep[x] - 1] % p];
  in_0[x] += Map2[F1[x]];
  if (G1[x] == r) out_0[x]++, in_0[rt]++;
  if (F1[x] == r) in_0[x]++, out_0[rt]++;
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (y == fa || vis[y]) continue;
    Get(y, x, rt);
  }
}
void Add(int x, int fa) {
  Map1[F0[x]]++;
  Map2[G0[x]]++;
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (y == fa || vis[y]) continue;
    Add(y, x);
  }
}
void Calc(int x) {
  Map1.clear();
  Map2.clear();
  Dfs(x, 0, x);
  if (F1[x] == r) in_0[x]++, out_0[x]++;
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (vis[y]) continue;
    Dec(y, x);
    Get(y, x, x);
    Add(y, x);
  }
}
void Divide(int x) {
  Calc(x);
  vis[x] = 1;
  for (int i = h[x]; i; i = e[i].nxt) {
    int y = e[i].to;
    if (vis[y]) continue;
    mx[rt = 0] = n + 1;
    N = siz[y];
    getRt(y, 0);
    Divide(rt);
  }
}
int main() {
  n = read(), p = read(), k = read(), r = read() % p;
  for (int i = 1; i <= n; i++) val[i] = read() % p;
  for (int i = 2; i <= n; i++) {
    int u = read(), v = read();
    Link(u, v);
    Link(v, u);
  }
  Pow[0] = 1;
  inv[0] = 1;
  for (int i = 1; i <= n; i++) Pow[i] = Pow[i - 1] * k % p;
  for (int i = 1; i <= n; i++) inv[i] = ksm(Pow[i], p - 2, p);
  mx[rt = 0] = n + 1;
  N = n;
  getRt(1, 0);
  Divide(rt);
  long long Ans = 1ll * n * n * n;
  long long res = 0;
  for (int i = 1; i <= n; i++) {
    out_1[i] = n - out_0[i];
    in_1[i] = n - in_0[i];
  }
  for (int i = 1; i <= n; i++) {
    res += 2ll * out_0[i] * out_1[i];
    res += 1ll * out_0[i] * in_1[i];
    res += 1ll * out_1[i] * in_0[i];
    res += 2ll * in_0[i] * in_1[i];
  }
  cout << Ans - res / 2 << "\n";
  return 0;
}
