#include <bits/stdc++.h>
using namespace std;
int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while ('0' <= c && c <= '9') {
    x = (x << 3) + (x << 1) + c - '0';
    c = getchar();
  }
  return x * f;
}
int n, Y, K, X, cnt, h[100005], Tot, root, siz[100005], dp[100005], val[100005];
long long in1[100005], out1[100005], mk[100005], inv[100005];
bool vst[100005];
struct Edge {
  int to, next;
} a[100005 * 2];
void Add(int x, int y) {
  cnt++;
  a[cnt].to = y;
  a[cnt].next = h[x];
  h[x] = cnt;
}
int KSM(int a, int b) {
  long long res = a, ans = 1;
  while (b) {
    if (b & 1) ans = ans * res % Y;
    res = res * res % Y;
    b >>= 1;
  }
  return ans;
}
int Get(int x, int fa) {
  int ret = 1;
  for (int i = h[x]; i; i = a[i].next) {
    int y = a[i].to;
    if (!vst[y] && y != fa) ret += Get(y, x);
  }
  return ret;
}
void Find(int x, int fa) {
  siz[x] = 1;
  dp[x] = 0;
  for (int i = h[x]; i; i = a[i].next) {
    int y = a[i].to;
    if (!vst[y] && y != fa) {
      Find(y, x);
      siz[x] += siz[y];
      dp[x] = max(dp[x], siz[y]);
    }
  }
  dp[x] = max(dp[x], Tot - siz[x]);
  if (dp[x] < dp[root]) root = x;
}
struct node {
  long long val;
  int id;
  bool operator<(const node &w) const { return val < w.val; }
} t1[100005], t2[100005];
void dfs(int x, int fa, int p, long long Gn, long long Gt) {
  Gn = (Gn * K + val[x]) % Y;
  if (p) Gt = (Gt + val[x] * mk[p - 1]) % Y;
  cnt++;
  t1[cnt].id = x;
  t1[cnt].val = (X - Gn + Y) * inv[p + 1] % Y;
  t2[cnt].id = x;
  t2[cnt].val = Gt;
  for (int i = h[x]; i; i = a[i].next) {
    int y = a[i].to;
    if (!vst[y] && y != fa) dfs(y, x, p + 1, Gn, Gt);
  }
}
void calc(int x, int f, int p, long long Gn, long long Gt) {
  cnt = 0;
  dfs(x, 0, p, Gn, Gt);
  sort(t1 + 1, t1 + cnt + 1);
  sort(t2 + 1, t2 + cnt + 1);
  int res = 0, i, j;
  for (i = j = 1; i <= cnt; ++i) {
    while (j <= cnt && t2[j].val <= t1[i].val) {
      if (j == 1 || t2[j].val != t2[j - 1].val) res = 0;
      res++;
      j++;
    }
    if (j != 1 && t2[j - 1].val == t1[i].val) out1[t1[i].id] += res * f;
  }
  res = 0;
  for (i = j = 1; j <= cnt; ++j) {
    while (i <= cnt && t1[i].val <= t2[j].val) {
      if (i == 1 || t1[i].val != t1[i - 1].val) res = 0;
      res++;
      i++;
    }
    if (i != 1 && t1[i - 1].val == t2[j].val) in1[t2[j].id] += res * f;
  }
}
void Divide(int x) {
  vst[x] = 1;
  calc(x, 1, 0, 0, 0);
  for (int i = h[x]; i; i = a[i].next) {
    int y = a[i].to;
    if (!vst[y]) calc(y, -1, 1, val[x], 0);
  }
  for (int i = h[x]; i; i = a[i].next) {
    int y = a[i].to;
    if (vst[y]) continue;
    Tot = Get(y, 0);
    root = 0;
    Find(y, 0);
    Divide(root);
  }
}
int main() {
  n = read();
  Y = read();
  K = read();
  X = read();
  for (int i = 1; i <= n; ++i) val[i] = read();
  int invk = KSM(K, Y - 2);
  inv[0] = 1;
  mk[0] = 1;
  for (int i = 1; i <= n; ++i) {
    inv[i] = inv[i - 1] * invk % Y;
    mk[i] = mk[i - 1] * K % Y;
  }
  for (int i = 1; i < n; ++i) {
    int x = read(), y = read();
    Add(x, y);
    Add(y, x);
  }
  Tot = n;
  cnt = root = 0;
  dp[0] = 0x7fffffff / 2;
  Find(1, 0);
  Divide(root);
  long long Ans = 0;
  for (int i = 1; i <= n; ++i) {
    int in0 = n - in1[i], out0 = n - out1[i];
    Ans +=
        2 * in0 * in1[i] + 2 * out0 * out1[i] + in1[i] * out0 + in0 * out1[i];
  }
  printf("%lld\n", 1ll * n * n * n - Ans / 2);
}
