#include <bits/stdc++.h>
using namespace std;
#pragma GCC diagnostic ignored "-Wmissing-declarations"
int const mod = 1e9 + 7;
inline void safe_add(int& x, const int y) {
  x += y;
  if (x >= mod) x -= mod;
}
inline int safe_mul(const int x, const int y) { return x * 1LL * y % mod; }
inline void upd(pair<int, int>& l, pair<int, int> r) {
  if (l.first < r.first) {
    l = r;
  } else {
    if (l.first == r.first) safe_add(l.second, r.second);
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> a(n);
  for (int& x : a) cin >> x;
  vector<vector<int>> grass(n + 1);
  for (int i = 0; i < n; ++i) grass[a[i]].push_back(i);
  vector<vector<int>> cows(n + 1);
  vector<pair<int, int>> rawc;
  for (int i = 0; i < m; ++i) {
    int f, h;
    cin >> f >> h;
    cows[f].push_back(h);
    rawc.emplace_back(f, h);
  }
  for (auto& vec : cows) sort(begin(vec), end(vec));
  pair<int, int> ans = {0, 0};
  for (auto& pa : rawc) {
    if (grass[pa.first].size() < pa.second) continue;
    int bord = grass[pa.first][pa.second - 1];
    int best = 1;
    int bcnt = 1;
    for (int type = 0; type <= n; ++type) {
      if (type != pa.first) {
        int cl = end(grass[type]) -
                 lower_bound(begin(grass[type]), end(grass[type]), bord);
        int cr = grass[type].size() - cl;
        if (cl > cr) swap(cl, cr);
        int ir = upper_bound(begin(cows[type]), end(cows[type]), cr) -
                 cows[type].begin();
        int il = upper_bound(begin(cows[type]), end(cows[type]), cl) -
                 cows[type].begin();
        if (ir > 0) {
          if (il > 0 && ir > 1) {
            best += 2;
            int tmp = 0;
            safe_add(tmp, il * (il - 1));
            safe_add(tmp, (ir - il) * il);
            bcnt = safe_mul(bcnt, tmp);
          } else {
            best += 1;
            int tmp = ir + il;
            bcnt = safe_mul(bcnt, tmp);
          }
        }
      } else {
        int need = grass[type].size() - pa.second;
        int ir = upper_bound(begin(cows[type]), end(cows[type]), need) -
                 cows[type].begin();
        if (ir > 0 && cows[type][ir - 1] >= pa.second) --ir;
        if (ir > 0) {
          best += 1;
          bcnt = safe_mul(bcnt, ir);
        }
      }
    }
    upd(ans, make_pair(best, bcnt));
  }
  int best = 0;
  int bcnt = 1;
  for (int type = 0; type <= n; ++type) {
    int need = grass[type].size();
    int ir = upper_bound(begin(cows[type]), end(cows[type]), need) -
             cows[type].begin();
    if (ir > 0) {
      best += 1;
      bcnt = safe_mul(bcnt, ir);
    }
  }
  upd(ans, make_pair(best, bcnt));
  cout << ans.first << ' ' << ans.second << endl;
}
