#include <bits/stdc++.h>
using namespace std;
const int MaxN = 1e5 + 100;
const int MaxM = 2e5 + 100;
const int inf = 1e9;
int point[MaxN], nxt[MaxM], v[MaxM], tot = 0;
int n, k;
long long value[MaxN], X, Y, inv[MaxN], pw[MaxN];
long long in[MaxN][2], out[MaxN][2];
bool cut[MaxN];
int f[MaxN], fa[MaxN], size[MaxN], cur[MaxN], cntIn, cntOut;
map<int, int> inDy, outDy;
inline void addedge(int x, int y) {
  tot++;
  nxt[tot] = point[x];
  point[x] = tot;
  v[tot] = y;
  tot++;
  nxt[tot] = point[y];
  point[y] = tot;
  v[tot] = x;
}
inline int getnum() {
  int ans = 0;
  char c;
  bool flag = false;
  while ((c = getchar()) == ' ' || c == '\n' || c == '\r')
    ;
  if (c == '-')
    flag = true;
  else
    ans = c - '0';
  while ((c = getchar()) >= '0' && c <= '9') ans = ans * 10 + c - '0';
  return ans * (flag ? -1 : 1);
}
inline long long qE(long long a, int p, long long mod) {
  long long ans = 1;
  for (; p; p >>= 1, a = a * a % mod)
    if (p & 1) ans = ans * a % mod;
  return ans;
}
inline void init() {
  for (int i = 1; i <= n; i++) {
    pw[i] = qE(k, i, Y);
    inv[i] = qE(pw[i], Y - 2, Y);
  }
}
inline int query(map<int, int> &Map, int x) {
  map<int, int>::iterator p = Map.find(x);
  if (p != Map.end())
    return (*p).second;
  else
    return 0;
}
inline void add(map<int, int> &Map, int x, int v) {
  map<int, int>::iterator p = Map.find(x);
  if (p != Map.end())
    (*p).second += v;
  else
    Map[x] = v;
}
inline int calcSize(int now, int fa) {
  int size = 1;
  for (int tmp = point[now], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (u != fa && !cut[u]) size += calcSize(u, now);
  return size;
}
inline void calcRoot(int now, int fa, int totNode, int &minn, int &wh) {
  size[now] = 1;
  f[now] = 0;
  for (int tmp = point[now], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (u != fa && !cut[u]) {
      calcRoot(u, now, totNode, minn, wh);
      size[now] += size[u];
      f[now] = max(f[now], size[u]);
    }
  f[now] = max(f[now], totNode - size[now]);
  if (f[now] < minn) minn = f[now], wh = now;
}
inline void calcOut(int now, long long lastRm, int fa, int deep, int delta) {
  long long remain = (lastRm + value[now] * pw[deep]) % Y;
  add(outDy, remain, delta);
  cntOut += delta;
  for (int tmp = point[now], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (u != fa && !cut[u]) calcOut(u, remain, now, deep + 1, delta);
}
inline void countOut(int now, long long lastRm, int fa, int deep, int delta) {
  long long remain = (lastRm * k + value[now]) % Y;
  long long A = (X + Y - remain) % Y * inv[deep] % Y;
  long long res = query(outDy, A);
  out[now][0] += res;
  out[now][1] += cntOut - res;
  add(inDy, A, delta);
  cntIn += delta;
  for (int tmp = point[now], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (u != fa && !cut[u]) countOut(u, remain, now, deep + 1, delta);
}
inline void countIn(int now, long long lastRm, int fa, int deep, int delta) {
  long long remain = (lastRm + value[now] * pw[deep]) % Y;
  long long res = query(inDy, remain);
  in[now][0] += res;
  in[now][1] += cntIn - res;
  for (int tmp = point[now], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (u != fa && !cut[u]) countIn(u, remain, now, deep + 1, delta);
}
inline void solve(int node) {
  int minn = inf, root = 0, totNode = calcSize(node, 0);
  calcRoot(node, 0, totNode, minn, root);
  cut[root] = true;
  for (int tmp = point[root], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (!cut[u]) solve(u);
  inDy.clear();
  outDy.clear();
  cntIn = 0;
  cntOut = 0;
  add(outDy, value[root], 1);
  cntOut++;
  for (int tmp = point[root], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (!cut[u]) calcOut(u, value[root], 0, 1, 1);
  long long res = query(outDy, X);
  out[root][0] += res;
  out[root][1] += cntOut - res;
  add(inDy, X, 1);
  cntIn++;
  for (int tmp = point[root], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (!cut[u]) countOut(u, 0, 0, 1, 1);
  res = query(inDy, value[root]);
  in[root][0] += res;
  in[root][1] += cntIn - res;
  for (int tmp = point[root], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (!cut[u]) countIn(u, value[root], 0, 1, 1);
  for (int tmp = point[root], u; u = v[tmp], tmp; tmp = nxt[tmp])
    if (!cut[u]) {
      inDy.clear();
      outDy.clear();
      cntIn = 0;
      cntOut = 0;
      calcOut(u, value[root], 0, 1, -1);
      countOut(u, 0, 0, 1, -1);
      countIn(u, value[root], 0, 1, -1);
    }
  cut[root] = false;
}
int main() {
  n = getnum();
  Y = getnum();
  k = getnum();
  X = getnum();
  X %= Y;
  for (int i = 1; i <= n; i++) value[i] = getnum() % Y;
  for (int i = 1; i < n; i++) {
    int x, y;
    x = getnum();
    y = getnum();
    addedge(x, y);
  }
  init();
  solve(1);
  long long ans = (long long)n * n * n * 2;
  for (int i = 1; i <= n; i++)
    ans -= 2 * in[i][0] * in[i][1] + 2 * out[i][0] * out[i][1] +
           in[i][0] * out[i][1] + in[i][1] * out[i][0];
  ans /= 2;
  cout << ans << endl;
}
