#include <bits/stdc++.h>
using namespace std;
const int MAX_SIZE = 100000;
int mod, tar, n, bas;
int val[MAX_SIZE + 10], in[MAX_SIZE + 10], out[MAX_SIZE + 10];
inline void inc(int& a, int b) {
  a += b;
  if (a >= mod) a -= mod;
}
int fastPow(int b, int p) {
  int cur = b % mod, ans = 1;
  while (p) {
    if (p & 1) ans = (int)((long long)ans * cur % mod);
    p >>= 1;
    cur = (int)((long long)cur * cur % mod);
  }
  return ans;
}
inline int calcInv(int a) { return fastPow(a, mod - 2); }
int nodes[MAX_SIZE + 10], to[MAX_SIZE * 2 + 10], nxt[MAX_SIZE * 2 + 10];
int en;
int intot[MAX_SIZE + 10], outtot[MAX_SIZE + 10], insub[MAX_SIZE + 10],
    outsub[MAX_SIZE + 10];
int totn, subn, ss[MAX_SIZE + 10], iv[MAX_SIZE + 10], ov[MAX_SIZE + 10];
inline void addEdge(int f, int t) {
  ++en;
  to[en] = t;
  nxt[en] = nodes[f];
  nodes[f] = en;
}
int size[MAX_SIZE + 10];
bool vis[MAX_SIZE + 10];
int root, minn, tot;
void dfsSize(int cur, int fa) {
  size[cur] = 1;
  for (int e = nodes[cur]; e; e = nxt[e]) {
    if (to[e] == fa || vis[to[e]]) continue;
    dfsSize(to[e], cur);
    size[cur] += size[to[e]];
  }
}
inline int max(int a, int b) { return a > b ? a : b; }
void findRoot(int cur, int fa) {
  int maxn = tot - size[cur];
  for (int e = nodes[cur]; e; e = nxt[e]) {
    if (to[e] == fa || vis[to[e]]) continue;
    findRoot(to[e], cur);
    maxn = max(maxn, size[to[e]]);
  }
  if (maxn < minn) {
    minn = maxn;
    root = cur;
  }
}
void dfs1(int cur, int fa, int pre, int k, int sum) {
  inc(sum, (int)((long long)val[cur] * k % mod));
  outtot[totn] = (int)((long long)bas * sum % mod);
  inc(outtot[totn], val[root]);
  pre = (int)((long long)pre * bas % mod);
  inc(pre, val[cur]);
  k = (int)((long long)k * bas % mod);
  intot[totn] = (int)((long long)(tar - pre + mod) * calcInv(k) % mod);
  ++totn;
  for (int e = nodes[cur]; e; e = nxt[e]) {
    if (to[e] == fa || vis[to[e]]) continue;
    dfs1(to[e], cur, pre, k, sum);
  }
}
void dfs2(int cur, int fa, int pre, int k, int sum) {
  ss[subn] = cur;
  inc(sum, (int)((long long)val[cur] * k % mod));
  outsub[subn] = (int)((long long)bas * sum % mod);
  inc(outsub[subn], val[root]);
  ov[cur] = outsub[subn];
  pre = (int)((long long)pre * bas % mod);
  inc(pre, val[cur]);
  k = (int)((long long)k * bas % mod);
  insub[subn] = (int)((long long)(tar - pre + mod) * calcInv(k) % mod);
  iv[cur] = insub[subn];
  ++subn;
  for (int e = nodes[cur]; e; e = nxt[e]) {
    if (to[e] == fa || vis[to[e]]) continue;
    dfs2(to[e], cur, pre, k, sum);
  }
}
void work(int cur) {
  dfsSize(cur, 0);
  tot = size[cur];
  minn = 0x3f3f3f3f;
  findRoot(cur, 0);
  cur = root;
  vis[cur] = true;
  if (val[cur] % mod == tar) {
    ++in[cur];
    ++out[cur];
  }
  totn = 1;
  outtot[0] = val[cur];
  intot[0] = tar;
  for (int e = nodes[cur]; e; e = nxt[e])
    if (!vis[to[e]]) dfs1(to[e], 0, 0, 1, 0);
  sort(outtot, outtot + totn);
  sort(intot, intot + totn);
  for (int e = nodes[cur]; e; e = nxt[e]) {
    if (!vis[to[e]]) {
      subn = 0;
      dfs2(to[e], 0, 0, 1, 0);
      sort(outsub, outsub + subn);
      sort(insub, insub + subn);
      for (int i = 0; i < subn; i++) {
        in[ss[i]] += (upper_bound(intot, intot + totn, ov[ss[i]]) -
                      lower_bound(intot, intot + totn, ov[ss[i]])) -
                     (upper_bound(insub, insub + subn, ov[ss[i]]) -
                      lower_bound(insub, insub + subn, ov[ss[i]]));
        if (ov[ss[i]] == tar) ++out[cur];
        out[ss[i]] += (upper_bound(outtot, outtot + totn, iv[ss[i]]) -
                       lower_bound(outtot, outtot + totn, iv[ss[i]])) -
                      (upper_bound(outsub, outsub + subn, iv[ss[i]]) -
                       lower_bound(outsub, outsub + subn, iv[ss[i]]));
        if (iv[ss[i]] == val[cur]) ++in[cur];
      }
    }
  }
  for (int e = nodes[cur]; e; e = nxt[e]) {
    if (!vis[to[e]]) {
      work(to[e]);
    }
  }
}
int main() {
  scanf("%d%d%d%d", &n, &mod, &bas, &tar);
  for (int i = 1; i <= n; i++) scanf("%d", val + i);
  for (int i = 1; i < n; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    addEdge(a, b);
    addEdge(b, a);
  }
  work(1);
  long long sum = 0;
  for (int i = 1; i <= n; i++)
    sum += (long long)in[i] * (n - in[i]) * 2LL +
           (long long)in[i] * (n - out[i]) + (long long)(n - in[i]) * out[i] +
           (long long)(n - out[i]) * out[i] * 2LL;
  printf(
      "%I64d"
      "\n",
      (long long)n * n * n - (sum >> 1));
  return 0;
}
