Problem: There are n players numbered from 0 to n-1 with ranks. The i-th player has rank i.

Players can form teams: the team should consist of three players and no pair of players in the team should have a conflict. The rank of the team is calculated using the following algorithm: let i, j, k be the ranks of players in the team and i < j < k, then the rank of the team is equal to A ⋅ i + B ⋅ j + C ⋅ k.

You are given information about the pairs of players who have a conflict. Calculate the total sum of ranks over all possible valid teams modulo 2^{64}.

Input

The first line contains two space-separated integers n and m (3 ≤ n ≤ 2 ⋅ 10^5, 0 ≤ m ≤ 2 ⋅ 10^5) — the number of players and the number of conflicting pairs.

The second line contains three space-separated integers A, B and C (1 ≤ A, B, C ≤ 10^6) — coefficients for team rank calculation.

Each of the next m lines contains two space-separated integers u_i and v_i (0 ≤ u_i, v_i < n, u_i ≠ v_i) — pair of conflicting players.

It's guaranteed that each unordered pair of players appears in the input file no more than once.

Output

Print single integer — the total sum of ranks over all possible teams modulo 2^{64}.

Examples

Input

4 0
2 3 4


Output

64


Input

4 1
2 3 4
1 0


Output

38


Input

6 4
1 5 3
0 3
3 5
5 4
4 3


Output

164

Note

In the first example all 4 teams are valid, i.e. triples: {0, 1, 2}, {0, 1, 3}, {0, 2, 3} {1, 2, 3}.

In the second example teams are following: {0, 2, 3}, {1, 2, 3}.

In the third example teams are following: {0, 1, 2}, {0, 1, 4}, {0, 1, 5}, {0, 2, 4}, {0, 2, 5}, {1, 2, 3}, {1, 2, 4}, {1, 2, 5}.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
int n, m, a, b, c, sqrtm;
const int MAXN = 2e5 + 5;
const int LIM = (1 << 25) - 1;
inline int read() {
  int x = 0;
  char c = getchar();
  while (c < '0' || c > '9') c = getchar();
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x;
}
struct edge {
  int u, to, next;
} e[MAXN << 1], g[MAXN];
int head[MAXN], cnt = 0, in[MAXN];
inline void add(int u, int v) {
  e[++cnt] = (edge){u, v, head[u]}, head[u] = cnt, in[u]++;
}
int ghead[MAXN], gcnt = 0;
inline void gadd(int u, int v) {
  g[++gcnt] = (edge){u, v, ghead[u]}, ghead[u] = gcnt;
}
struct halist {
  int u, v, next;
} ha[MAXN << 1];
int hahead[LIM + 1], tim = 0;
inline long long gethash(int x, int y) {
  return (1ll * x * 200753 + y) % 19260817;
}
inline void addhash(int x, int y) {
  long long t = gethash(x, y);
  ha[++tim] = (halist){x, y, hahead[t]}, hahead[t] = tim;
}
bool getedge(int x, int y) {
  long long t = gethash(x, y);
  for (int i = hahead[t]; i; i = ha[i].next)
    if (ha[i].u == x && ha[i].v == y) return 1;
  return 0;
}
unsigned long long solve1() {
  unsigned long long tmp = 0, ans = 0;
  for (int i = 0; i < n; i++) {
    int t1 = n - i - 1;
    ans += 1ll * t1 * (t1 - 1) / 2 * a * i;
    ans += 1ll * i * (i - 1) / 2 * c * i;
    ans += 1ll * i * (n - i - 1) * b * i;
  }
  return ans;
}
int vec[MAXN], smal[MAXN], bigg[MAXN], tp = 0, points = 0, pointb = 0;
long long presum[MAXN], bsum = 0, ssum = 0;
unsigned long long solve2() {
  unsigned long long ans = 0;
  for (int u = 2; u < n; u++) {
    tp = 0;
    for (int i = head[u]; i; i = e[i].next) {
      if (e[i].to < u) {
        ans += 1ll * (u - 1) * u * c;
        ans += 1ll * e[i].to * e[i].to * b;
        ans += 1ll * e[i].to * (u - e[i].to - 1) * a;
        ans += 1ll * (e[i].to - 1) * e[i].to / 2 * a;
        ans += 1ll * (e[i].to + u) * (u - e[i].to - 1) / 2 * b;
        vec[++tp] = e[i].to;
      }
    }
    if (tp <= 1) continue;
    sort(vec + 1, vec + 1 + tp);
    for (int i = 1; i <= tp; i++) presum[i] = presum[i - 1] + vec[i];
    for (int i = 1; i <= tp; i++) {
      ans -= 1ll * u * (i - 1) * c;
      ans -= 1ll * vec[i] * b * (i - 1);
      ans -= presum[i - 1] * a;
    }
  }
  return ans;
}
long long sortd[10];
int tid = 0, isheavy[MAXN];
char existd[MAXN];
bitset<MAXN> B[1111];
unsigned long long solve3() {
  unsigned long long ans = 0;
  for (int u = 0; u < n; u++) {
    tp = 0, points = 0, pointb = 0, bsum = 0;
    for (int i = head[u]; i; i = e[i].next) {
      int v = e[i].to;
      if (u < v) {
        ans += 1ll * u * (n - v - 1) * a;
        ans += 1ll * v * (n - v - 1) * b;
        ans += 1ll * (v + n) * (n - v - 1) / 2 * c;
        vec[++tp] = v;
        bigg[++pointb] = v;
        bsum += v;
      } else
        smal[++points] = v;
    }
    sort(vec + 1, vec + 1 + tp);
    for (int i = 1; i <= tp; i++) presum[i] = presum[i - 1] + vec[i];
    for (int i = 1; i <= tp; i++) {
      ans -= 1ll * u * (tp - i) * a;
      ans -= 1ll * vec[i] * (tp - i) * b;
      ans -= 1ll * (presum[tp] - presum[i]) * c;
    }
    for (int i = 1; i <= points; i++) {
      ans -= 1ll * smal[i] * pointb * a;
      ans -= 1ll * u * pointb * b;
      ans -= 1ll * bsum * c;
    }
  }
  long long base = 0, sqrtm = 450;
  memset(isheavy, 0, sizeof(isheavy));
  for (int u = 0; u < n; u++) {
    if (in[u] >= sqrtm) {
      isheavy[u] = ++tid;
      for (int i = head[u]; i; i = e[i].next) {
        int v = e[i].to;
        B[tid][v] = 1;
      }
    }
  }
  for (int u = 0; u < n; u++) {
    if (!isheavy[u]) {
      for (int i = head[u]; i; i = e[i].next) {
        int dv = e[i].to;
        if (dv > u) break;
        if (!isheavy[dv]) {
          for (int j = head[dv]; j; j = e[j].next) {
            int du = e[j].to;
            if (du > dv) break;
            existd[du] = 1;
          }
          for (int j = head[u]; j; j = e[j].next) {
            int du = e[j].to;
            if (existd[du] == 1)
              ans += 1ll * a * du + 1ll * b * dv + 1ll * c * u;
          }
          for (int j = head[dv]; j; j = e[j].next) {
            int du = e[j].to;
            if (du > dv) break;
            existd[du] = 0;
          }
        } else {
          for (int j = head[u]; j; j = e[j].next) {
            int du = e[j].to;
            if (du > dv) break;
            if (B[isheavy[dv]][du])
              ans += 1ll * a * du + 1ll * b * dv + 1ll * c * u;
          }
        }
      }
    } else {
      for (int i = 1; i <= cnt; i++) {
        int du = e[i].u, dv = e[i].to;
        if (du > u || dv > u || du > dv) continue;
        if (B[isheavy[u]][du] && B[isheavy[u]][dv])
          ans += 1ll * a * du + 1ll * b * dv + 1ll * c * u;
      }
    }
  }
  return ans;
}
struct duru {
  int x, y;
} dr[MAXN * 2];
bool cmp1(duru a, duru b) { return a.y > b.y; }
int main() {
  memset(existd, 0, sizeof(existd));
  n = read(), m = read(), a = read(), b = read(), c = read();
  for (int i = 1; i <= m; i++) {
    int x, y;
    dr[i * 2 - 1].x = read(), dr[i * 2 - 1].y = read();
    dr[i * 2].x = dr[i * 2 - 1].y;
    dr[i * 2].y = dr[i * 2 - 1].x;
  }
  sort(dr + 1, dr + 1 + m * 2, cmp1);
  for (int i = 1; i <= 2 * m; i++) add(dr[i].x, dr[i].y);
  unsigned long long tot, sub1, sub2;
  tot = solve1();
  sub1 = solve2();
  sub2 = solve3();
  cout << tot - sub1 - sub2 << endl;
  return 0;
}