#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll long long
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  ll z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  ll z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  ll z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            ways *= k1;
          else
            ways *= k1 + 1;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++;
          else
            c += 2, w *= k1 * k2 - min(k1, k2);
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w *= k1;
          else
            w *= k2;
        }
      }
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w *= k;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll int
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  ll z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  ll z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  ll z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            w *= k1;
          else
            w *= k1 + 1;
          w %= mod;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++, w *= 2;
          else
            c += 2, w *= k1 * k2 - min(k1, k2);
          w %= mod;
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w *= k1;
          else
            w *= k2;
          w %= mod;
        }
      }
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
    // cout << ans << ' ' << ways << '\n';
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w *= k;
      w %= mod;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll int
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  ll z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  ll z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  ll z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            ways *= k1;
          else
            ways *= k1 + 1;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++;
          else
            c += 2, w *= k1 * k2 - min(k1, k2);
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w *= k1;
          else
            w *= k2;
        }
      }
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w *= k;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll int
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  x %= mod;
  y %= mod;
  ll z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  ll z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  ll z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            w *= k1 % mod;
          else
            w *= (k1 + 1) % mod;
          w %= mod;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++, w *= 2;
          else
            c += 2, w *= sub(mul(k1, k2, mod), min(k1, k2), mod);
          w %= mod;
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w *= k1;
          else
            w *= k2;
          w %= mod;
        }
      }
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
    // cout << ans << ' ' << ways << '\n';
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w *= k;
      w %= mod;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll int
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  if (x < 0)
    x += mod;
  if (y < 0)
    y += mod;
  x %= mod;
  y %= mod;
  long long z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  if (x < 0)
    x += mod;
  if (y < 0)
    y += mod;
  x %= mod;
  y %= mod;
  long long z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  if (x < 0)
    x += mod;
  if (y < 0)
    y += mod;
  x %= mod;
  y %= mod;
  long long z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            w = mul(w, k1, mod);
          else
            w = mul(w, (k1 + 1), mod);
          w %= mod;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++, w = mul(w, 2, mod);
          else
            c += 2, w = mul(w, sub(mul(k1, k2, mod), min(k1, k2), mod), mod);
          if (w < 0)
            w += mod;
          w %= mod;
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w = mul(w, k1, mod);
          else
            w = mul(w, k2, mod);
          w %= mod;
        }
        if (w < 0)
          w += mod;
      }
      if (w < 0)
        w += mod;
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
    // cout << ans << ' ' << ways << '\n';
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w = mul(w, k, mod);
      w %= mod;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll int
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  ll z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  ll z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  ll z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            ways *= k1;
          else
            ways *= k1 + 1;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++, w *= 2;
          else
            c += 2, w *= k1 * k2 - min(k1, k2);
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w *= k1;
          else
            w *= k2;
        }
      }
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
    // cout << ans << ' ' << ways << '\n';
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w *= k;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>
/*    #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;       */
using namespace std;

#define ll int
#define ull unsigned long long
#define f(a, b) for (ll i = a; i < b; i++)
#define mod 1000000007
#define pb push_back
#define vll vector<ll>
#define pll vector<pair<ll, ll>>
#define ld long double
#define fr(a, b) for (ll j = a; j >= b; j--)
#define fi(a, b) for (ll j = a; j < b; j++)
#define fii(a, b) for (ll k = a; k < b; k++)
//      typedef tree<ll
//      ,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//      ordered_set;

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V)
    os << v << " ";
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S)
    os << s << " ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M)
    os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}

inline ll mul(ll x, ll y, ll m) {
  x %= mod;
  y %= mod;
  ll z = 1LL * x * y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll add(ll x, ll y, ll m) {
  ll z = x + y;
  if (z >= m)
    z %= m;
  return z;
}
inline ll sub(ll x, ll y, ll m) {
  ll z = x - y;
  if (z < 0)
    z += m;
  z %= m;
  return z;
}

const ll N = 5005;
ll n, m, a[N], f[N], h[N], tot[N], pr[N][N], su[N][N];
vll v[N];

int main() {
#ifndef ONLINE_JUDGE
  freopen("input.txt", "rt", stdin);
  freopen("output.txt", "wt", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  cin >> n >> m;
  f(1, n + 1) cin >> a[i], tot[a[i]]++, pr[a[i]][i]++;
  f(1, n + 1) fi(1, n + 1) pr[i][j] += pr[i][j - 1],
      su[i][j] = tot[i] - pr[i][j];
  f(1, m + 1) {
    ll f, h;
    cin >> f >> h;
    v[f].pb(h);
  }
  f(1, n + 1) sort(v[i].begin(), v[i].end());
  ll ans = 0, ways = 1;
  f(1, n + 1) { // left finish at i
    ll l = pr[a[i]][i];
    ll l1 = lower_bound(v[a[i]].begin(), v[a[i]].end(), l) - v[a[i]].begin();
    if (l1 == v[a[i]].size() || l != v[a[i]][l1])
      continue;
    // cout << i << ' ' << l << ' ' << v[a[i]][l1] << '\n';
    ll c = 0, w = 1;
    fi(1, n + 1) {
      if (j == a[i]) { // left wla is fixed
        ll k = su[j][i];
        ll k1 = upper_bound(v[j].begin(), v[j].end(), k) - v[j].begin() - 1;
        if (k1 != -1) {
          if (k1 == 0 && v[j][k1] == l) {
            c++;
            continue;
          }
          c += 2;
          if (v[j][k1] >= l)
            w = mul(w, k1, mod);
          else
            w = mul(w, (k1 + 1), mod);
          w %= mod;
        } else {
          c++;
        }
      } else {
        ll k1 = upper_bound(v[j].begin(), v[j].end(), pr[j][i]) - v[j].begin();
        ll k2 = upper_bound(v[j].begin(), v[j].end(), su[j][i]) - v[j].begin();
        if (k1 != 0 && k2 != 0) {
          if (k1 == k2 && k1 == 1)
            c++, w = mul(w, 2, mod);
          else
            c += 2, w = mul(w, sub(mul(k1, k2, mod), min(k1, k2), mod), mod);
          w %= mod;
        } else if (k1 == 0 && k2 == 0) {
          continue;
        } else {
          c++;
          if (k1 != 0)
            w = mul(w, k1, mod);
          else
            w = mul(w, k2, mod);
          w %= mod;
        }
      }
      if (w < 0)
        w += mod;
    }
    // cout << c << ' ' << w << "\n\n";
    if (c > ans)
      ans = c, ways = w;
    else if (c == ans)
      ways = add(ways, w, mod);
    // cout << ans << ' ' << ways << '\n';
  }
  // include proper suffix
  ll c = 0, w = 1;
  f(1, n + 1) {
    if (v[i].size() > 0) {
      ll k = upper_bound(v[i].begin(), v[i].end(), tot[i]) - v[i].begin();
      if (k != 0)
        c++, w = mul(w, k, mod);
      w %= mod;
    }
  }
  if (c == ans && c != 0)
    ways = add(ways, w, mod);
  // cout << c << ' ' << w << '\n';
  cout << ans << ' ' << ways << '\n';

#ifndef ONLINE_JUDGE
  cout << "\nTime Elapsed : " << 1000 * (ld)clock() / (ld)CLOCKS_PER_SEC
       << " ms\n";
#endif
  return 0;
}


#include <bits/stdc++.h>

#define int long long
#define f first

#define s second
using namespace std;

template<typename T> using vc = vector<T>;
using pii=pair<int, int>;

void xmax(int & a, int b){
    a=max(a, b);
}
void xmin(int& a, int b){
    a=min(a, b);
}

void print(vc <int> & a, string s){
    cerr << s << " : ";
    for (int i=0; i<a.size(); i++){
        cerr <<a[i] << " ";
    }
    cerr << endl;
}
int mod = 1e9+7;
vc <vc <int> > bi (5003, vc <int> (5003, -1));
int binom (int a, int b){
    if (bi[a][b]!=-1) return bi[a][b];
    if (b == 0) return 1;
    if (a == 1) return 1;
    return bi[a][b] = (binom(a, b-1)+ binom(a-1, b-1))%mod;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    #ifdef LOCAL_RUN
    freopen("input.txt", "r", stdin);
    int ttt;
    cin >> ttt;
    while(ttt--){
    #endif // LOCAL_RUN

    int n, m;
    cin >> n >> m;
    vc <int> s (n);
    for (int i=0; i<n; i++){
        cin >> s[i];
    }
    vc <pii> c (m);
    for (int i=0; i<m; i++){
        cin >> c[i].f >> c[i].s;
    }
    vc <int> ls (n, -1);
    vc <int> rs (n, -1);
    for (int i=0; i<m; i++){
        int anz = 0;
        int ind = 0;
        while(anz<c[i].s && ind < n){
            if (c[i].f == s[ind]) anz++;
            ind++;
        }
        if (anz == c[i].s )ls[ind-1] = i;
        anz = 0;
        ind = n-1;
      //  cout << "da" << endl;
        while(anz < c[i].s && ind >=0){
            if(c[i].f ==s[ind] ) anz++;
            ind--;
        }
       // cout << ind << " " << n << endl;
        if (anz == c[i].s) rs[ind+1] = i;
    }
    //cout << "here" << endl;
    int maxi = 0;
    int sum = 1;

    vc <unordered_set<int> > left (n+1);
    vc <unordered_set<int> > right (n+1);
    for (int i=0; i<n; i++){
        if (rs[i]!=-1) right[s[i]].insert(rs[i]);
    }
    int e = 1;

    for (int i=0; i<=n; i++){
        if (right[i].size()>0) maxi++;
        int r = right[i].size();
        sum = (sum * max(r, e))%mod;
    }
   // cout << maxi << "\n";
  //  print(rs, "rs");
   // print(ls, "ls");
 //   cout << maxi << " m s" << sum << endl;
    for (int i=0; i<n; i++){
        // i indicates how many grass_fields will eat from the left and how many from the right
   //     cout << "round " << i << endl;
        if (ls[i] == -1) continue;
        if (rs[i]!=-1){
            right[s[i]].erase(rs[i]);
        }
        left[s[i]].insert(ls[i]);
        int f = s[i];
        int col = i;
        int cur = 0;
        int anz_lonely = 0;
        for (int j=0; j<=n; j++){
            if (right[j].size()==0){
                if (left[j].size()!=0){
                    cur++;
                }
            }
            if (right[j].size() == 1){
                cur++;
                if (left[j].size()>=2){
                    cur++;
                }
                if (left[j].size()==1){
                    //cout << "*da" << endl;
                    auto tap = left[j].begin();
                    auto tapii = right[j].begin();
                  //  cout << " what nodes << " << *tap << " " << *tapii <<  " " << "at " << i <<endl;
                    if (*tap == *tapii){
                        anz_lonely++;
                        if (j == f) {
                            anz_lonely--;
                        }
                    }else{
                        cur++;
                    }
                }
            }
            if (right[j].size() >=2){
                cur ++;

                if (left[j].size()>=1){
                    cur++;
                }
            }
        }
    //    cout << "here" << endl;
        left[s[i]].erase(ls[i]);
        if (cur > maxi){
            maxi = cur;
            sum = 0;
        }
      //  cout << cur << " " <<i << endl;
        if (cur < maxi) continue;
        int mult = 1;
        for (int j=0; j<=n; j++){
            int r = right[j].size();
            int l = left[j].size();
            if (j == f){
                if (right[j].find(ls[i])!=right[j].end()){
                    mult=(mult*max(r-1 , e))%mod;
                }else{
                    mult= (mult*max(r, e)) % mod;
                }
            }else{
                mult = (mult*max(r, e))%mod;
                mult = (mult*max(l, e))%mod;
            }

        }
        //cout << mult << " " << anz_lonely << " " << endl;
        for (int j=0; j<=anz_lonely; j++){
            sum = (sum + binom(anz_lonely, j) *mult)%mod;
        }
        left[s[i]].insert(ls[i]);
        //cout << maxi << " m s" << sum <<  " index " << i << endl;

    }
    cout << maxi << " " <<  sum << "\n";

    #ifdef LOCAL_RUN
    }
    #endif // LOCAL_RUN
}


#include <bits/stdc++.h>

#define int long long
#define f first

#define s second
using namespace std;

template<typename T> using vc = vector<T>;
using pii=pair<int, int>;

void xmax(int & a, int b){
    a=max(a, b);
}
void xmin(int& a, int b){
    a=min(a, b);
}

void print(vc <int> & a, string s){
    cerr << s << " : ";
    for (int i=0; i<a.size(); i++){
        cerr <<a[i] << " ";
    }
    cerr << endl;
}
int mod = 1e9+7;
vc <vc <int> > bi (5003, vc <int> (5003, -1));
int binom (int a, int b){
    if (bi[a][b]!=-1) return bi[a][b];
    if (b == 0) return 1;
    if (a == 1) return 1;
    return bi[a][b] = (binom(a, b-1)+ binom(a-1, b-1))%mod;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    #ifdef LOCAL_RUN
    freopen("input.txt", "r", stdin);
    int ttt;
    cin >> ttt;
    while(ttt--){
    #endif // LOCAL_RUN

    int n, m;
    cin >> n >> m;
    vc <int> s (n);
    for (int i=0; i<n; i++){
        cin >> s[i];
    }
    vc <pii> c (m);
    for (int i=0; i<m; i++){
        cin >> c[i].f >> c[i].s;
    }
    vc <int> ls (n, -1);
    vc <int> rs (n, -1);
    for (int i=0; i<m; i++){
        int anz = 0;
        int ind = 0;
        while(anz<c[i].s && ind < n){
            if (c[i].f == s[ind]) anz++;
            ind++;
        }
        if (anz == c[i].s )ls[ind-1] = i;
        anz = 0;
        ind = n-1;
      //  cout << "da" << endl;
        while(anz < c[i].s && ind >=0){
            if(c[i].f ==s[ind] ) anz++;
            ind--;
        }
       // cout << ind << " " << n << endl;
        if (anz == c[i].s) rs[ind+1] = i;
    }
    //cout << "here" << endl;
    int maxi = 0;
    int sum = 1;

    vc <unordered_set<int> > left (n+1);
    vc <unordered_set<int> > right (n+1);
    for (int i=0; i<n; i++){
        if (rs[i]!=-1) right[s[i]].insert(rs[i]);
    }
    int e = 1;

    for (int i=0; i<=n; i++){
        if (right[i].size()>0) maxi++;
        int r = right[i].size();
        sum = (sum * max(r, e))%mod;
    }
   // cout << maxi << "\n";
   // print(rs, "rs");
    //print(ls, "ls");
   // cout << maxi << " m s" << sum << endl;
    for (int i=0; i<n; i++){
        // i indicates how many grass_fields will eat from the left and how many from the right
   //     cout << "round " << i << endl;
        if (rs[i]!=-1){
            right[s[i]].erase(rs[i]);
        }
        if (ls[i] == -1) continue;

        left[s[i]].insert(ls[i]);
        int f = s[i];
        int cur = 0;
        int anz_lonely = 0;
        for (int j=0; j<=n; j++){

            if (right[j].size() == 1 && left[j].size() == 1){
                if (*(right.begin()) == *(left.begin())){
                    cur++;
                    if (j!=f) anz_lonely++;
                }else{
                    cur+=2;
                }
            }else{
                if (right[j].size()>=1) cur++;
                if (left[j].size()>=1) cur++;
            }

            /*if (right[j].size()==0){
                if (left[j].size()!=0){
                    cur++;
                }
            }
            if (right[j].size() == 1){
                cur++;
                if (left[j].size()>=2){
                    cur++;
                }
                if (left[j].size()==1){
                    //cout << "*da" << endl;
                    auto tap = left[j].begin();
                    auto tapii = right[j].begin();
                  //  cout << " what nodes << " << *tap << " " << *tapii <<  " " << "at " << i <<endl;
                    if (*tap == *tapii){
                        anz_lonely++;
                        if (j == f) {
                            anz_lonely--;
                        }
                    }else{
                        cur++;
                    }
                }
            }
            if (right[j].size() >=2){
                cur++;
                if (left[j].size()>=1){
                    cur++;
                }
            }*/
        }
    //    cout << "here" << endl;

        if (cur > maxi){
            maxi = cur;
            sum = 0;
        }
      //  cout << cur << " " <<i << endl;
        if (cur < maxi) continue;
        //cout << "--------------------------------------------" << endl;
        //cout  << "index : " << i << endl;
        int mult = 1;
        for (int j=0; j<=n; j++){
           // cout << "col: " << j << endl;
            int r = right[j].size();
            int l = left[j].size();
            if (j == f){
                if (right[j].find(ls[i])!=right[j].end()){
                    mult=(mult*max(r-1 , e))%mod;
                }else{
                    mult= (mult*max(r, e)) % mod;
                }
            }else{
                // have to get rid of joint things
                int joint = 0;
                for (auto x : right[j]) {
                    if (left[j].find(x)!=left[j].end()) joint++;
                }
                //cout << joint << " " << l << " " << r << endl;

                int m = (l-joint)*r + joint*(r-joint) + joint*(joint-1);
                if (l == 0) m = r;
                if (r == 0) m = l;
               // cout << "m " << m << endl;
                m%=mod;
                mult = (mult*max(m, e))%mod;
            }

        }
        /*cout << "--------------------------------------------" << endl;
        cout  << "index : " << i << endl;
        cout << "right " << endl;
        for (int j = 0; j<right.size(); j++){
            cout << "color " << j << " : ";
            for (auto x : right[j]){
                cout << x << " ";
            }
            cout << "\n";
        }
        cout << "left" << endl;
         for (int j = 0; j<left.size(); j++){
            cout << "color " << j << " : ";
            for (auto x : right[j]){
                cout << x << " ";
            }
            cout << "\n";
        }*/

        for (int j=0; j<=anz_lonely; j++){
            sum = (sum + binom(anz_lonely, j) *mult)%mod;
        }

        //cout << maxi << " m s" << sum <<  " index " << i << endl;

    }
    cout << maxi << " " <<  sum << "\n";

    #ifdef LOCAL_RUN
    }
    #endif // LOCAL_RUN
}


#include <bits/stdc++.h>

#define int long long
#define f first

#define s second
using namespace std;

template<typename T> using vc = vector<T>;
using pii=pair<int, int>;

void xmax(int & a, int b){
    a=max(a, b);
}
void xmin(int& a, int b){
    a=min(a, b);
}

void print(vc <int> & a, string s){
    cerr << s << " : ";
    for (int i=0; i<a.size(); i++){
        cerr <<a[i] << " ";
    }
    cerr << endl;
}
int mod = 1e9+7;
vc <vc <int> > bi (5003, vc <int> (5003, -1));
int binom (int a, int b){
    if (bi[a][b]!=-1) return bi[a][b];
    if (b == 0) return 1;
    if (a == 1) return 1;
    if (a == b) return 1;
    return bi[a][b] = (binom(a-1, b-1)+ binom(a-1, b))%mod;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    #ifdef LOCAL_RUN
    freopen("input.txt", "r", stdin);
    int ttt;
    cin >> ttt;
    while(ttt--){
    #endif // LOCAL_RUN

    int n, m;
    cin >> n >> m;
    vc <int> s (n);
    for (int i=0; i<n; i++){
        cin >> s[i];
    }
    vc <pii> c (m);
    for (int i=0; i<m; i++){
        cin >> c[i].f >> c[i].s;
    }
    vc <int> ls (n, -1);
    vc <int> rs (n, -1);
    for (int i=0; i<m; i++){
        int anz = 0;
        int ind = 0;
        while(anz<c[i].s && ind < n){
            if (c[i].f == s[ind]) anz++;
            ind++;
        }
        if (anz == c[i].s )ls[ind-1] = i;
        anz = 0;
        ind = n-1;
      //  cout << "da" << endl;
        while(anz < c[i].s && ind >=0){
            if(c[i].f ==s[ind] ) anz++;
            ind--;
        }
       // cout << ind << " " << n << endl;
        if (anz == c[i].s) rs[ind+1] = i;
    }
    //cout << "here" << endl;
    int maxi = 0;
    int sum = 1;

    vc <unordered_set<int> > left (n+1);
    vc <unordered_set<int> > right (n+1);
    for (int i=0; i<n; i++){
        if (rs[i]!=-1) right[s[i]].insert(rs[i]);
    }
    int e = 1;

    for (int i=0; i<=n; i++){
        if (right[i].size()>0) maxi++;
        int r = right[i].size();
        sum = (sum * max(r, e))%mod;
    }
   // cout << maxi << "\n";
   // print(rs, "rs");
    //print(ls, "ls");
   // cout << maxi << " m s" << sum << endl;
   /*for (int i=0;i<=6; i++){
    for (int j=0; j<=i; j++){
        cout << binom(i, j) << " ";
    }
    cout << "\n";
   }*/
    for (int i=0; i<n; i++){
        // i indicates how many grass_fields will eat from the left and how many from the right
   //     cout << "round " << i << endl;
        if (rs[i]!=-1){
            right[s[i]].erase(rs[i]);
        }
        if (ls[i] == -1) continue;

        left[s[i]].insert(ls[i]);
        int f = s[i];
        int cur = 0;
        int anz_lonely = 0;
        for (int j=0; j<=n; j++){

            if (right[j].size() == 1 && left[j].size() == 1){
                if (*(right.begin()) == *(left.begin())){
                    cur++;
                    if (j!=f) anz_lonely++;
                }else{
                    cur+=2;
                }
            }else{
                if (right[j].size()>=1) cur++;
                if (left[j].size()>=1) cur++;
            }
        }
    //    cout << "here" << endl;

        if (cur > maxi){
            maxi = cur;
            sum = 0;
        }
      //  cout << cur << " " <<i << endl;
        if (cur < maxi) continue;
        //cout << "--------------------------------------------" << endl;
        //cout  << "index : " << i << endl;
        int mult = 1;
        for (int j=0; j<=n; j++){
           // cout << "col: " << j << endl;
            int r = right[j].size();
            int l = left[j].size();
            if (j == f){
                if (right[j].find(ls[i])!=right[j].end()){
                    mult=(mult*max(r-1 , e))%mod;
                }else{
                    mult= (mult*max(r, e)) % mod;
                }
            }else{
                // have to get rid of joint things
                int joint = 0;
                for (auto x : right[j]) {
                    if (left[j].find(x)!=left[j].end()) joint++;
                }
                //cout << joint << " " << l << " " << r << endl;

                int m = (l-joint)*r + joint*(r-joint) + joint*(joint-1);
                if (l == 0) m = r;
                if (r == 0) m = l;
               // cout << "m " << m << endl;
                m = m%mod;
                mult = (mult*max(m, e))%mod;
            }

        }

        for (int j=0; j<=anz_lonely; j++){
            sum = (sum + binom(anz_lonely, j) *mult)%mod;
        }

        //cout << maxi << " m s" << sum <<  " index " << i << endl;

    }
    cout << maxi << " " <<  sum << "\n";

    #ifdef LOCAL_RUN
    }
    #endif // LOCAL_RUN
}


#include <bits/stdc++.h>

#define int long long
#define f first

#define s second
using namespace std;

template<typename T> using vc = vector<T>;
using pii=pair<int, int>;

void xmax(int & a, int b){
    a=max(a, b);
}
void xmin(int& a, int b){
    a=min(a, b);
}

void print(vc <int> & a, string s){
    cerr << s << " : ";
    for (int i=0; i<a.size(); i++){
        cerr <<a[i] << " ";
    }
    cerr << endl;
}
int mod = 1e9+7;
vc <vc <int> > bi (5003, vc <int> (5003, -1));
int binom (int a, int b){
    if (bi[a][b]!=-1) return bi[a][b];
    if (b == 0) return 1;
    if (a == 1) return 1;
    return bi[a][b] = (binom(a, b-1)+ binom(a-1, b-1))%mod;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    #ifdef LOCAL_RUN
    freopen("input.txt", "r", stdin);
    int ttt;
    cin >> ttt;
    while(ttt--){
    #endif // LOCAL_RUN

    int n, m;
    cin >> n >> m;
    vc <int> s (n);
    for (int i=0; i<n; i++){
        cin >> s[i];
    }
    vc <pii> c (m);
    for (int i=0; i<m; i++){
        cin >> c[i].f >> c[i].s;
    }
    vc <int> ls (n, -1);
    vc <int> rs (n, -1);
    for (int i=0; i<m; i++){
        int anz = 0;
        int ind = 0;
        while(anz<c[i].s && ind < n){
            if (c[i].f == s[ind]) anz++;
            ind++;
        }
        if (anz == c[i].s )ls[ind-1] = i;
        anz = 0;
        ind = n-1;
      //  cout << "da" << endl;
        while(anz < c[i].s && ind >=0){
            if(c[i].f ==s[ind] ) anz++;
            ind--;
        }
       // cout << ind << " " << n << endl;
        if (anz == c[i].s) rs[ind+1] = i;
    }
    //cout << "here" << endl;
    int maxi = 0;
    int sum = 1;

    vc <unordered_set<int> > left (n+1);
    vc <unordered_set<int> > right (n+1);
    for (int i=0; i<n; i++){
        if (rs[i]!=-1) right[s[i]].insert(rs[i]);
    }
    int e = 1;

    for (int i=0; i<=n; i++){
        if (right[i].size()>0) maxi++;
        int r = right[i].size();
        sum = (sum * max(r, e))%mod;
    }
   // cout << maxi << "\n";
   // print(rs, "rs");
    //print(ls, "ls");
   // cout << maxi << " m s" << sum << endl;
    for (int i=0; i<n; i++){
        // i indicates how many grass_fields will eat from the left and how many from the right
   //     cout << "round " << i << endl;
        if (rs[i]!=-1){
            right[s[i]].erase(rs[i]);
        }
        if (ls[i] == -1) continue;

        left[s[i]].insert(ls[i]);
        int f = s[i];
        int col = i;
        int cur = 0;
        int anz_lonely = 0;
        for (int j=0; j<=n; j++){
            if (right[j].size()==0){
                if (left[j].size()!=0){
                    cur++;
                }
            }
            if (right[j].size() == 1){
                cur++;
                if (left[j].size()>=2){
                    cur++;
                }
                if (left[j].size()==1){
                    //cout << "*da" << endl;
                    auto tap = left[j].begin();
                    auto tapii = right[j].begin();
                  //  cout << " what nodes << " << *tap << " " << *tapii <<  " " << "at " << i <<endl;
                    if (*tap == *tapii){
                        anz_lonely++;
                        if (j == f) {
                            anz_lonely--;
                        }
                    }else{
                        cur++;
                    }
                }
            }
            if (right[j].size() >=2){
                cur ++;

                if (left[j].size()>=1){
                    cur++;
                }
            }
        }
    //    cout << "here" << endl;
        left[s[i]].erase(ls[i]);
        if (cur > maxi){
            maxi = cur;
            sum = 0;
        }
      //  cout << cur << " " <<i << endl;
        if (cur < maxi) continue;
        int mult = 1;
        for (int j=0; j<=n; j++){
            int r = right[j].size();
            int l = left[j].size();
            if (j == f){
                if (right[j].find(ls[i])!=right[j].end()){
                    mult=(mult*max(r-1 , e))%mod;
                }else{
                    mult= (mult*max(r, e)) % mod;
                }
            }else{
                mult = (mult*max(r, e))%mod;
                mult = (mult*max(l, e))%mod;
            }

        }
        /*cout << "--------------------------------------------" << endl;
        cout  << "index : " << i << endl;
        cout << "right " << endl;
        for (int j = 0; j<right.size(); j++){
            cout << "color " << j << " : ";
            for (auto x : right[j]){
                cout << x << " ";
            }
            cout << "\n";
        }
        cout << "left" << endl;
         for (int j = 0; j<left.size(); j++){
            cout << "color " << j << " : ";
            for (auto x : right[j]){
                cout << x << " ";
            }
            cout << "\n";
        }*/

        for (int j=0; j<=anz_lonely; j++){
            sum = (sum + binom(anz_lonely, j) *mult)%mod;
        }
        left[s[i]].insert(ls[i]);
        //cout << maxi << " m s" << sum <<  " index " << i << endl;

    }
    cout << maxi << " " <<  sum << "\n";

    #ifdef LOCAL_RUN
    }
    #endif // LOCAL_RUN
}


#include <bits/stdc++.h>

#define int long long
#define f first

#define s second
using namespace std;

template<typename T> using vc = vector<T>;
using pii=pair<int, int>;

void xmax(int & a, int b){
    a=max(a, b);
}
void xmin(int& a, int b){
    a=min(a, b);
}

void print(vc <int> & a, string s){
    cerr << s << " : ";
    for (int i=0; i<a.size(); i++){
        cerr <<a[i] << " ";
    }
    cerr << endl;
}
int mod = 1e9+7;
vc <vc <int> > bi (5003, vc <int> (5003, -1));
int binom (int a, int b){
    if (bi[a][b]!=-1) return bi[a][b];
    if (b == 0) return 1;
    if (a == 1) return 1;
    return bi[a][b] = (binom(a, b-1)+ binom(a-1, b-1))%mod;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    #ifdef LOCAL_RUN
    freopen("input.txt", "r", stdin);
    int ttt;
    cin >> ttt;
    while(ttt--){
    #endif // LOCAL_RUN

    int n, m;
    cin >> n >> m;
    vc <int> s (n);
    for (int i=0; i<n; i++){
        cin >> s[i];
    }
    vc <pii> c (m);
    for (int i=0; i<m; i++){
        cin >> c[i].f >> c[i].s;
    }
    vc <int> ls (n, -1);
    vc <int> rs (n, -1);
    for (int i=0; i<m; i++){
        int anz = 0;
        int ind = 0;
        while(anz<c[i].s && ind < n){
            if (c[i].f == s[ind]) anz++;
            ind++;
        }
        if (anz == c[i].s )ls[ind-1] = i;
        anz = 0;
        ind = n-1;
      //  cout << "da" << endl;
        while(anz < c[i].s && ind >=0){
            if(c[i].f ==s[ind] ) anz++;
            ind--;
        }
       // cout << ind << " " << n << endl;
        if (anz == c[i].s) rs[ind+1] = i;
    }
    //cout << "here" << endl;
    int maxi = 0;
    int sum = 1;

    vc <unordered_set<int> > left (n+1);
    vc <unordered_set<int> > right (n+1);
    for (int i=0; i<n; i++){
        if (rs[i]!=-1) right[s[i]].insert(rs[i]);
    }
    int e = 1;

    for (int i=0; i<=n; i++){
        if (right[i].size()>0) maxi++;
        int r = right[i].size();
        sum = (sum * max(r, e))%mod;
    }
   // cout << maxi << "\n";
   // print(rs, "rs");
    //print(ls, "ls");
   // cout << maxi << " m s" << sum << endl;
    for (int i=0; i<n; i++){
        // i indicates how many grass_fields will eat from the left and how many from the right
   //     cout << "round " << i << endl;
        if (rs[i]!=-1){
            right[s[i]].erase(rs[i]);
        }
        if (ls[i] == -1) continue;

        left[s[i]].insert(ls[i]);
        int f = s[i];
        int cur = 0;
        int anz_lonely = 0;
        for (int j=0; j<=n; j++){

            if (right[j].size() == 1 && left[j].size() == 1){
                if (*(right.begin()) == *(left.begin())){
                    cur++;
                    if (j!=f) anz_lonely++;
                }else{
                    cur+=2;
                }
            }else{
                if (right[j].size()>=1) cur++;
                if (left[j].size()>=1) cur++;
            }

            /*if (right[j].size()==0){
                if (left[j].size()!=0){
                    cur++;
                }
            }
            if (right[j].size() == 1){
                cur++;
                if (left[j].size()>=2){
                    cur++;
                }
                if (left[j].size()==1){
                    //cout << "*da" << endl;
                    auto tap = left[j].begin();
                    auto tapii = right[j].begin();
                  //  cout << " what nodes << " << *tap << " " << *tapii <<  " " << "at " << i <<endl;
                    if (*tap == *tapii){
                        anz_lonely++;
                        if (j == f) {
                            anz_lonely--;
                        }
                    }else{
                        cur++;
                    }
                }
            }
            if (right[j].size() >=2){
                cur++;
                if (left[j].size()>=1){
                    cur++;
                }
            }*/
        }
    //    cout << "here" << endl;

        if (cur > maxi){
            maxi = cur;
            sum = 0;
        }
      //  cout << cur << " " <<i << endl;
        if (cur < maxi) continue;
        int mult = 1;
        for (int j=0; j<=n; j++){
            int r = right[j].size();
            int l = left[j].size();
            if (j == f){
                if (right[j].find(ls[i])!=right[j].end()){
                    mult=(mult*max(r-1 , e))%mod;
                }else{
                    mult= (mult*max(r, e)) % mod;
                }
            }else{
                mult = (mult*max(r, e))%mod;
                mult = (mult*max(l, e))%mod;
            }

        }
        /*cout << "--------------------------------------------" << endl;
        cout  << "index : " << i << endl;
        cout << "right " << endl;
        for (int j = 0; j<right.size(); j++){
            cout << "color " << j << " : ";
            for (auto x : right[j]){
                cout << x << " ";
            }
            cout << "\n";
        }
        cout << "left" << endl;
         for (int j = 0; j<left.size(); j++){
            cout << "color " << j << " : ";
            for (auto x : right[j]){
                cout << x << " ";
            }
            cout << "\n";
        }*/

        for (int j=0; j<=anz_lonely; j++){
            sum = (sum + binom(anz_lonely, j) *mult)%mod;
        }

        //cout << maxi << " m s" << sum <<  " index " << i << endl;

    }
    cout << maxi << " " <<  sum << "\n";

    #ifdef LOCAL_RUN
    }
    #endif // LOCAL_RUN
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define F first
#define S second
#define pb push_back
mt19937 rnd;

#define div divi

const int mod = 1e9 + 7;

inline int add(int a, int b) {
    if (a + b >= mod) return a + b - mod;
    else return a + b;
}

inline int sub(int a, int b) {
    if (a - b < 0) return a - b + mod;
    else return a - b;
}

inline int mult(int a, int b) {
    return 1ll * a * b % mod;
}

inline int binpow(int a, int n) {
    int res = 1;
    while (n) {
        if (n & 1) {
            res = mult(res, a);
        }
        a = mult(a, a);
        n >>= 1;
    }
    return res;
}

inline int inv(int a) {
    return binpow(a, mod - 2);
}

inline int div(int a, int b) {
    return mult(a, inv(b));
}

struct Cow {
    int f, h;
    int lef = 0, rig = 0;
};

struct Answer {
    int val = 0, cnt = 1;
};

#define left leftt
#define right rightt

const int N = 5e3 + 10;
int n, m;
int s[N], cnt1[N];
vector<int> a[N];
Answer ans[N];
int left[N];
int right[N];
bool mark[N];

pii calc(int f, int x) {
    if (a[f].empty() || a[f][0] > x) {
        return {0, 1};
    }
    return {1, upper_bound(a[f].begin(), a[f].end(), x) - a[f].begin()};
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif

    cin >> n >> m;
    for (int i=1; i<=n; i++) {
        cin >> s[i];
        cnt1[s[i]]++;
    }
    for (int i=1; i<=m; i++) {
        int f, h;
        cin >> f >> h;
        if (h <= cnt1[f]) {
            a[f].pb(h);
            for (int j=1, cnt=0; j<=n; j++) {
                if (s[j] == f) cnt++;
                if (cnt == h) {
                    mark[j] = 1;
                    break;
                }
            }
        }
    }
    for (int i=1; i<=n; i++) {
        sort(a[i].begin(), a[i].end());
    }
    for (int i=n; i>=1; i--) {
        right[s[i]]++;
    }
    for (int f=1; f<=n; f++) {
        if (a[f].empty()) continue;
        ans[0].val++;
        ans[0].cnt = mult(ans[0].cnt, a[f].size());
    }
    for (int i=1; i<=n; i++) {
        right[s[i]]--;
        left[s[i]]++;
        if (!mark[i]) continue;
        for (int f=1; f<=n; f++) {
            pii lef = calc(f, left[f]);
            pii rig = calc(f, right[f]);
            pii both = calc(f, min(left[f], right[f]));
            if (f == s[i]) {
                if (right[f] >= left[f]) {
                    if (rig.S == 1) {
                        rig = {0, 1};
                    }
                    else {
                        rig.S--;
                    }
                }
                if (rig.F) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, rig.S);
                }
                else {
                    ans[i].val += 1;
                }
            }
            else {
                if (lef.F && rig.F && max(lef.S, rig.S) >= 2) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, sub(mult(lef.S, rig.S), both.S));
                }
                else {
                    if (lef.F || rig.F) {
                        ans[i].val += 1;
                        ans[i].cnt = mult(ans[i].cnt, add(lef.S * lef.F, rig.S * rig.F));
                    }
                }
            }
        }
    }
    int mx = 0;
    for (int i=0; i<=n; i++) {
        mx = max(mx, ans[i].val);
    }
    int cnt = 0;
    for (int i=0; i<=n; i++) {
        if (ans[i].val == mx) {
            cnt = add(cnt, ans[i].cnt);
        }
    }
    if (mx == 0) {
        cnt = 1;
    }
    cout << mx << " " << cnt << "\n";

#ifdef LOCAL
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
   return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define F first
#define S second
#define pb push_back
mt19937 rnd;

#define div divi

const int mod = 1e9 + 7;

inline int add(int a, int b) {
    if (a + b >= mod) return a + b - mod;
    else return a + b;
}

inline int sub(int a, int b) {
    if (a - b < 0) return a - b + mod;
    else return a - b;
}

inline int mult(int a, int b) {
    return 1ll * a * b % mod;
}

inline int binpow(int a, int n) {
    int res = 1;
    while (n) {
        if (n & 1) {
            res = mult(res, a);
        }
        a = mult(a, a);
        n >>= 1;
    }
    return res;
}

inline int inv(int a) {
    return binpow(a, mod - 2);
}

inline int div(int a, int b) {
    return mult(a, inv(b));
}

struct Cow {
    int f, h;
    int lef = 0, rig = 0;
};

struct Answer {
    int val = 0, cnt = 1;
};

#define left leftt
#define right rightt

const int N = 5e3 + 10;
int s[N];
int cnt1[N];
vector<int> a[N];
Answer ans[N];
int left[N];
int right[N];
bool mark[N];

pii calc(int f, int x) {
    if (a[f].empty() || a[f][0] > x) return {0, 1};
    return {1, upper_bound(a[f].begin(), a[f].end(), x) - a[f].begin()};
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif

    int n, m;
    cin >> n >> m;
    for (int i=1; i<=n; i++) {
        cin >> s[i];
        cnt1[s[i]]++;
    }
    for (int i=1; i<=m; i++) {
        int f, h;
        cin >> f >> h;
        if (cnt1[f] < h) continue;
        a[f].pb(h);
        for (int j=1, cnt=0; j<=n; j++) {
            if (s[j] == f) cnt++;
            if (cnt == h) {
                mark[j] = 1;
                break;
            }
        }
    }
    for (int i=1; i<=n; i++) {
        sort(a[i].begin(), a[i].end());
    }
    for (int i=n; i>=1; i--) {
        right[s[i]]++;
    }
    for (int f=1; f<=n; f++) {
        if (a[f].empty()) continue;
        ans[0].val++;
        ans[0].cnt = mult(ans[0].cnt, a[f].size());
    }
    for (int i=1; i<=n; i++) {
        right[s[i]]--;
        left[s[i]]++;
        if (!mark[i]) continue;
        for (int f=1; f<=n; f++) {
            pii lef = calc(f, left[f]);
            pii rig = calc(f, right[f]);
            pii both = calc(f, min(left[f], right[f]));
            if (f == s[i]) {
                if (right[f] >= left[f]) {
                    if (rig.S == 1) rig = {0, 1};
                    else rig.S--;
                }
                if (rig.F) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, rig.S);
                }
                else {
                    ans[i].val += 1;
                }
            }
            else {
                if (lef.F && rig.F && max(lef.S, rig.S) >= 2) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, sub(mult(lef.S, rig.S), both.S));
                }
                else {
                    ans[i].val += (lef.F || rig.F);
                    ans[i].cnt = mult(ans[i].cnt, max(1, add(lef.S * lef.F, rig.S * rig.F)));
                }
            }
        }
    }
    int mx = 0, cnt = 0;
    for (int i=0; i<=n; i++) {
        if (mx < ans[i].val) {
            mx = ans[i].val;
            cnt = ans[i].cnt;
        }
        else if (mx == ans[i].val) {
            cnt = add(cnt, ans[i].cnt);
        }
    }
    if (mx == 0) cnt = 1;
    cout << mx << " " << cnt << "\n";

#ifdef LOCAL
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
   return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define F first
#define S second
#define pb push_back
mt19937 rnd;

#define div divi

const int mod = 1e9 + 7;

inline int add(int a, int b) {
    if (a + b >= mod) return a + b - mod;
    else return a + b;
}

inline int sub(int a, int b) {
    if (a - b < 0) return a - b + mod;
    else return a - b;
}

inline int mult(int a, int b) {
    return 1ll * a * b % mod;
}

inline int binpow(int a, int n) {
    int res = 1;
    while (n) {
        if (n & 1) {
            res = mult(res, a);
        }
        a = mult(a, a);
        n >>= 1;
    }
    return res;
}

inline int inv(int a) {
    return binpow(a, mod - 2);
}

inline int div(int a, int b) {
    return mult(a, inv(b));
}

struct Cow {
    int f, h;
    int lef = 0, rig = 0;
};

struct Answer {
    int val = 0, cnt = 1;
};

#define left leftt
#define right rightt

const int N = 5e3 + 10;
int s[N];
vector<int> a[N];
Answer ans[N];
int left[N];
int right[N];
bool mark[N];

pii calc(int f, int x) {
    if (a[f].empty() || a[f][0] > x) return {0, 1};
    return {1, upper_bound(a[f].begin(), a[f].end(), x) - a[f].begin()};
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif

    int n, m;
    cin >> n >> m;
    for (int i=1; i<=n; i++) {
        cin >> s[i];
    }
    for (int i=1; i<=m; i++) {
        int f, h;
        cin >> f >> h;
        a[f].pb(h);
        for (int j=1, cnt=0; j<=n; j++) {
            if (s[j] == f) cnt++;
            if (cnt == h) {
                mark[j] = 1;
                break;
            }
        }
    }
    for (int i=1; i<=n; i++) {
        sort(a[i].begin(), a[i].end());
    }
    for (int i=n; i>=1; i--) {
        right[s[i]]++;
    }
    for (int f=1; f<=n; f++) {
        if (a[f].empty()) continue;
        ans[0].val++;
        ans[0].cnt = mult(ans[0].cnt, a[f].size());
    }
    for (int i=1; i<=n; i++) {
        right[s[i]]--;
        left[s[i]]++;
        if (!mark[i]) continue;
        for (int f=1; f<=n; f++) {
            pii lef = calc(f, left[f]);
            pii rig = calc(f, right[f]);
            pii both = calc(f, min(left[f], right[f]));
            if (f == s[i]) {
                if (right[f] >= left[f]) {
                    if (rig.S == 1) rig = {0, 1};
                    else rig.S--;
                }
                if (rig.F) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, rig.S);
                }
                else {
                    ans[i].val += 1;
                }
            }
            else {
                if (lef.F && rig.F && max(lef.S, rig.S) >= 2) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, sub(mult(lef.S, rig.S), both.S));
                }
                else {
                    ans[i].val += (lef.F || rig.F);
                    ans[i].cnt = mult(ans[i].cnt, max(1, add(lef.S * lef.F, rig.S * rig.F)));
                }
            }
        }
    }
    int mx = 0, cnt = 0;
    for (int i=0; i<=n; i++) {
        if (mx < ans[i].val) {
            mx = ans[i].val;
            cnt = ans[i].cnt;
        }
        else if (mx == ans[i].val) {
            cnt = add(cnt, ans[i].cnt);
        }
    }
    if (mx == 0) cnt = 1;
    cout << mx << " " << cnt << "\n";

#ifdef LOCAL
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
   return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define F first
#define S second
#define pb push_back
mt19937 rnd;

const int mod = 1e9 + 7;

inline int add(int a, int b) {
    if (a + b >= mod) return a + b - mod;
    else return a + b;
}

inline int sub(int a, int b) {
    if (a - b < 0) return a - b + mod;
    else return a - b;
}

inline int mult(int a, int b) {
    return 1ll * a * b % mod;
}

struct Answer {
    int val = 0, cnt = 1;
};

#define left leftt
#define right rightt

const int N = 5e3 + 10;
int s[N];
int cnt1[N];
vector<int> a[N];
Answer ans[N];
int left[N];
int right[N];
bool mark[N];

pii calc(int f, int x) {
    if (a[f].empty() || a[f][0] > x) return {0, 1};
    return {1, upper_bound(a[f].begin(), a[f].end(), x) - a[f].begin()};
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif

    int n, m;
    cin >> n >> m;
    for (int i=1; i<=n; i++) {
        cin >> s[i];
        cnt1[s[i]]++;
    }
    for (int i=1; i<=m; i++) {
        int f, h;
        cin >> f >> h;
        if (cnt1[f] < h) continue;
        a[f].pb(h);
        for (int j=1, cnt=0; j<=n; j++) {
            if (s[j] == f) cnt++;
            if (cnt == h) {
                mark[j] = 1;
                break;
            }
        }
    }
    for (int i=1; i<=n; i++) {
        sort(a[i].begin(), a[i].end());
    }
    for (int i=n; i>=1; i--) {
        right[s[i]]++;
    }
    for (int f=1; f<=n; f++) {
        if (a[f].empty()) continue;
        ans[0].val++;
        ans[0].cnt = mult(ans[0].cnt, a[f].size());
    }
    for (int i=1; i<=n; i++) {
        right[s[i]]--;
        left[s[i]]++;
        if (!mark[i]) continue;
        for (int f=1; f<=n; f++) {
            pii lef = calc(f, left[f]);
            pii rig = calc(f, right[f]);
            pii both = calc(f, min(left[f], right[f]));
            if (f == s[i]) {
                if (right[f] >= left[f]) {
                    if (rig.S == 1) rig = {0, 1};
                    else rig.S--;
                }
                if (rig.F) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, rig.S);
                }
                else {
                    ans[i].val += 1;
                }
            }
            else {
                if (lef.F && rig.F && max(lef.S, rig.S) >= 2) {
                    ans[i].val += 2;
                    ans[i].cnt = mult(ans[i].cnt, sub(mult(lef.S, rig.S), both.S));
                }
                else {
                    ans[i].val += (lef.F || rig.F);
                    ans[i].cnt = mult(ans[i].cnt, max(1, add(lef.S * lef.F, rig.S * rig.F)));
                }
            }
        }
    }
    int mx = 0, cnt = 0;
    for (int i=0; i<=n; i++) {
        if (mx < ans[i].val) {
            mx = ans[i].val;
            cnt = ans[i].cnt;
        }
        else if (mx == ans[i].val) {
            cnt = add(cnt, ans[i].cnt);
        }
    }
    if (mx == 0) cnt = 1;
    cout << mx << " " << cnt << "\n";

#ifdef LOCAL
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
   return 0;
}


#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cassert>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <random>
#include <fstream>
#include <bitset>
#include <cstring>
#include <limits.h>

#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define pll pair <ll, ll>
#define uint int

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef double ld;

const int maxn = 5010, mod = (int)1e9 + 7;
int s[maxn];
int f[maxn], h[maxn];
int cnt[maxn];

int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		scanf("%d", &s[i]);
		cnt[s[i]]++;
	}

	vector <pii> g;

	for (int i = 0; i < m; i++) {
		scanf("%d %d", &f[i], &h[i]);
		g.push_back(mp(f[i], h[i]));
	}

	sort(all(g));

	int num = 0;
	int ans = 1;
	int l = 0;

	while (l < m) {
		int r = l;

		while (r < m && g[r].first == g[l].first) {
			r++;
		}

		int x = g[l].second;

		if (x > cnt[g[l].first]) {
			l = r;
			continue;
		}

		if (l + 1 == r) {
			num++;
			ans += ans;
			if (ans >= mod) {
				ans -= mod;
			}
		}
		else {
			int y = g[l + 1].second;

			if (y > cnt[g[l].first]) {
				num++;
				ans += ans;
				if (ans >= mod) {
					ans -= mod;
				}
			}
			else if (x + y > cnt[g[l].first]) {
				num++;
				ans += ans;
				if (ans >= mod) {
					ans -= mod;
				}
				ans += ans;
				if (ans >= mod) {
					ans -= mod;
				}
			}
			else {
				num += 2;
				ans += ans;
				if (ans >= mod) {
					ans -= mod;
				}
			}
		}

		l = r;
	}

	cout << num << ' ' << ans << '\n';
}


#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cassert>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <random>
#include <fstream>
#include <bitset>
#include <cstring>
#include <limits.h>

#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define pll pair <ll, ll>
#define uint int

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;

const int maxn = 5010, mod = (int)1e9 + 7;
int cnt[maxn];
vector <int> wh[maxn];
int num[maxn];
int dp[2][maxn];
int le[maxn];
int s[maxn];

int add(int x, int y) {
	x += y;
	if (x >= mod) {
		x -= mod;
	}
	return x;
}

int mul(int x, int y) {
	return (ll)x * y % mod;
}

int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		int x;

		cin >> x;
		s[i] = x;
		cnt[x]++;
		wh[x].push_back(i);
	}

	vector <pii> g;

	for (int i = 0; i < m; i++) {
		int x, y;

		cin >> x >> y;
		g.push_back(mp(x, y));
	}

	sort(all(g));

	int numb = 0;
	int ans = 0;

	for (int d = 0; d <= n; d++) {
		if (d != 0) {
			dp[0][d] = 1;
		}
		else {
			dp[1][d] = 1;
		}

		num[d] = 0;

		int l = 0;

		memset(le, 0, sizeof le);

		for (int i = 0; i < d; i++) {
			le[s[i]]++;
		}

		while (l < m) {
			int r = l;
			int t = g[l].first;
			int numl = 0;
			int numr = 0;
			int numlr = 0;

			while (r < m && g[r].first == t) {
				if (g[r].second <= le[t]) {
					numl++;
				}

				if (g[r].second <= cnt[t] - le[t]) {
					numr++;
				}

				if (g[r].second <= le[t] && g[r].second <= cnt[t] - le[t]) {
					numlr++;
				}

				r++;
			}

			if (numl == 0 && numr == 0) {
				l = r;
				continue;
			}

			if (numl == 0 || numr == 0 || (numlr == 1 && numl == 1 && numr == 1)) {
				num[d]++;

				int cf = 0;
				int cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf++;
					}

					if ((x <= le[t] && wh[t][x - 1] + 1 != d)) {
						cf1++;
					}

					if (x <= cnt[t] - le[t]) {
						cf1++;
					}
				}

				dp[1][d] = add(mul(dp[1][d], cf1 + cf), mul(dp[0][d], cf));
				dp[0][d] = mul(dp[0][d], cf1);
			}
			else {
				num[d] += 2;

				ll cf = 0;
				ll cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;
					int z = 0;

					if (x <= le[t] && x <= cnt[t] - le[t]) {
						z = 1;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf += numr - z;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 != d) {
						cf1 += numr - z;
					}

					if (x <= cnt[t] - le[t]) {
						cf1 += numl - z;
					}
				}

				cf %= mod;
				cf1 %= mod;

				dp[1][d] = add(mul(dp[1][d], (int)cf1 + (int)cf), mul(dp[0][d], (int)cf));
				dp[0][d] = mul(dp[0][d], (int)cf1);
			}

			l = r;
		}

		if (num[d] > numb) {
			numb = num[d];
			ans = dp[1][d];
		}
		else if (num[d] == numb) {
			ans = add(ans, dp[1][d]);
		}
	}

	cout << numb << ' ' << ans << endl;
}


#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cassert>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <random>
#include <fstream>
#include <bitset>
#include <cstring>
#include <limits.h>

#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define pll pair <ll, ll>
#define uint int

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;

const int maxn = 5010, mod = (int)1e9 + 7;
int cnt[maxn];
vector <int> wh[maxn];
int num[maxn];
int dp[2][maxn];
int le[maxn];
int s[maxn];

int add(int x, int y) {
	x += y;
	if (x >= mod) {
		x -= mod;
	}
	return x;
}

int mul(int x, int y) {
	return (ll)x * y % mod;
}

int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		int x;

		cin >> x;
		s[i] = x;
		cnt[x]++;
		wh[x].push_back(i);
	}

	vector <pii> g;

	for (int i = 0; i < m; i++) {
		int x, y;

		cin >> x >> y;
		g.push_back(mp(x, y));
	}

	sort(all(g));

	int numb = 0;
	int ans = 0;

	for (int d = 0; d <= n; d++) {
		if (d != 0) {
			dp[0][d] = 1;
		}
		else {
			dp[1][d] = 1;
		}

		num[d] = 0;

		int l = 0;

		memset(le, 0, sizeof le);

		for (int i = 0; i < d; i++) {
			le[s[i]]++;
		}

		while (l < m) {
			int r = l;
			int t = g[l].first;
			int numl = 0;
			int numr = 0;
			int numlr = 0;

			while (r < m && g[r].first == t) {
				if (g[r].second <= le[t]) {
					numl++;
				}

				if (g[r].second <= cnt[t] - le[t]) {
					numr++;
				}

				if (g[r].second <= le[t] && g[r].second <= cnt[t] - le[t]) {
					numlr++;
				}

				r++;
			}

			if (numl == 0 && numr == 0) {
				l = r;
				continue;
			}

			if (numl == 0 || numr == 0 || (numlr == 1 && numl == 1 && numr == 1)) {
				num[d]++;

				int cf = 0;
				int cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf++;
					}

					if ((x <= le[t] && wh[t][x - 1] + 1 != d)) {
						cf1++;
					}

					if (x <= cnt[t] - le[t]) {
						cf1++;
					}
				}

				dp[1][d] = add(mul(dp[1][d], cf1 + cf), mul(dp[0][d], cf));
				dp[0][d] = mul(dp[0][d], cf1);
			}
			else {
				num[d] += 2;

				ll cf = 0;
				ll cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;
					int z = 0;

					if (x <= le[t] && x <= cnt[t] - le[t]) {
						z = 1;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf += numr - z;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 != d) {
						cf1 += numr - z;
					}
				}

				cf %= mod;
				cf1 %= mod;

				dp[1][d] = add(mul(dp[1][d], (int)cf1 + (int)cf), mul(dp[0][d], (int)cf));
				dp[0][d] = mul(dp[0][d], (int)cf1);
			}

			l = r;
		}

		if (num[d] > numb) {
			numb = num[d];
			ans = dp[1][d];
		}
		else if (num[d] == numb) {
			ans = add(ans, dp[1][d]);
		}
	}

	cout << numb << ' ' << ans << endl;
}


#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cassert>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <random>
#include <fstream>
#include <bitset>
#include <cstring>
#include <limits.h>

#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define pll pair <ll, ll>
#define uint int

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;

const int maxn = 5010, mod = (int)1e9 + 7;
int cnt[maxn];
vector <int> wh[maxn];
int num[maxn];
int dp[2][maxn];
int le[maxn];
int s[maxn];

int add(int x, int y) {
	x += y;
	if (x >= mod) {
		x -= mod;
	}
	return x;
}

int mul(int x, int y) {
	return (ll)x * y % mod;
}

int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		int x;

		cin >> x;
		s[i] = x;
		cnt[x]++;
		wh[x].push_back(i);
	}

	vector <pii> g;

	for (int i = 0; i < m; i++) {
		int x, y;

		cin >> x >> y;
		g.push_back(mp(x, y));
	}

	sort(all(g));

	int numb = 0;
	int ans = 0;

	for (int d = 0; d <= n; d++) {
		memset(dp, 0, sizeof dp);

		if (d != 0) {
			dp[0][d] = 1;
		}
		else {
			dp[1][d] = 1;
		}

		num[d] = 0;

		int l = 0;

		memset(le, 0, sizeof le);

		for (int i = 0; i < d; i++) {
			le[s[i]]++;
		}

		while (l < m) {
			int r = l;
			int t = g[l].first;
			int numl = 0;
			int numr = 0;
			int numlr = 0;

			while (r < m && g[r].first == t) {
				if (g[r].second <= le[t]) {
					numl++;
				}

				if (g[r].second <= cnt[t] - le[t]) {
					numr++;
				}

				if (g[r].second <= le[t] && g[r].second <= cnt[t] - le[t]) {
					numlr++;
				}

				r++;
			}

			if (numl == 0 && numr == 0) {
				l = r;
				continue;
			}

			if (numl == 0 || numr == 0 || (numlr == 1 && numl == 1 && numr == 1)) {
				num[d]++;

				int cf = 0;
				int cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf++;
					}

					if ((x <= le[t] && wh[t][x - 1] + 1 != d)) {
						cf1++;
					}

					if (x <= cnt[t] - le[t]) {
						cf1++;
					}
				}

				dp[1][d] = add(mul(dp[1][d], cf1), mul(dp[0][d], cf));
				dp[0][d] = mul(dp[0][d], cf1);
			}
			else {
				num[d] += 2;

				ll cf = 0;
				ll cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;
					int z = 0;

					if (x <= le[t] && x <= cnt[t] - le[t]) {
						z = 1;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf += numr - z;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 != d) {
						cf1 += numr - z;
					}

					if (x <= cnt[t] - le[t]) {
						cf1 += numl - z;
					}
				}

				cf %= mod;
				cf1 %= mod;

				dp[1][d] = add(mul(dp[1][d], (int)cf1), mul(dp[0][d], (int)cf));
				dp[0][d] = mul(dp[0][d], (int)cf1);
			}

			l = r;
		}

		if (num[d] > numb) {
			numb = num[d];
			ans = dp[1][d];
		}
		else if (num[d] == numb) {
			ans = add(ans, dp[1][d]);
		}
	}

	cout << numb << ' ' << ans << endl;
}


#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cassert>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <random>
#include <fstream>
#include <bitset>
#include <cstring>
#include <limits.h>

#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define pll pair <ll, ll>
#define uint int

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef double ld;

const int maxn = 5010, mod = (int)1e9 + 7;
int s[maxn];
int f[maxn], h[maxn];
int cnt[maxn];

int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		scanf("%d", &s[i]);
		cnt[s[i]]++;
	}

	vector <pii> g;

	for (int i = 0; i < m; i++) {
		scanf("%d %d", &f[i], &h[i]);
		g.push_back(mp(f[i], h[i]));
	}

	sort(all(g));

	int num = 0;
	int ans = 1;
	int l = 0;

	while (l < m) {
		int r = l;

		while (r < m && g[r].first == g[l].first) {
			r++;
		}

		int x = g[l].second;

		if (x > cnt[g[l].first]) {
			l = r;
			continue;
		}

		if (l + 1 == r) {
			num++;
			ans += ans;
			if (ans >= mod) {
				ans -= mod;
			}
		}
		else {
			int y = g[l + 1].second;

			if (x + y > cnt[g[l].first]) {
				num++;
				int cf = 0;

				for (int i = l; i < r; i++) {
					if (g[i].second <= cnt[g[l].first]) {
						cf++;
					}
				}

				cf = (ll)cf * 2 % mod;

				ans = (ll)ans * cf % mod;
			}
			else {
				num += 2;

				int pos = r - 1;
				ll cf = 0;

				for (int i = l; i < r; i++) {
					while (pos >= l && g[i].second + g[pos].second > cnt[g[l].first]) {
						pos--;
					}

					if (pos >= l) {
						if (pos < i) {
							cf += pos - l + 1;
						}
						else {
							cf += pos - l;
						}
					}
				}

				cf %= mod;
				ans = (ll)ans * cf % mod;
			}
		}

		l = r;
	}

	cout << num << ' ' << ans << '\n';
}


#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cassert>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <random>
#include <fstream>
#include <bitset>
#include <cstring>
#include <limits.h>

#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define pll pair <ll, ll>
#define uint int

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;

const int maxn = 5010, mod = (int)1e9 + 7;
int cnt[maxn];
vector <int> wh[maxn];
int num[maxn];
int dp[2][maxn];
int le[maxn];
int s[maxn];

int add(int x, int y) {
	x += y;
	if (x >= mod) {
		x -= mod;
	}
	return x;
}

int mul(int x, int y) {
	return (ll)x * y % mod;
}

int main() {
	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		int x;

		cin >> x;
		s[i] = x;
		cnt[x]++;
		wh[x].push_back(i);
	}

	vector <pii> g;

	for (int i = 0; i < m; i++) {
		int x, y;

		cin >> x >> y;
		g.push_back(mp(x, y));
	}

	sort(all(g));

	int numb = 0;
	int ans = 0;

	for (int d = 0; d <= n; d++) {
		if (d != 0) {
			dp[0][d] = 1;
		}
		else {
			dp[1][d] = 1;
		}

		num[d] = 0;

		int l = 0;

		memset(le, 0, sizeof le);

		for (int i = 0; i < d; i++) {
			le[s[i]]++;
		}

		while (l < m) {
			int r = l;
			int t = g[l].first;
			int numl = 0;
			int numr = 0;
			int numlr = 0;

			while (r < m && g[r].first == t) {
				if (g[r].second <= le[t]) {
					numl++;
				}

				if (g[r].second <= cnt[t] - le[t]) {
					numr++;
				}

				if (g[r].second <= le[t] && g[r].second <= cnt[t] - le[t]) {
					numlr++;
				}

				r++;
			}

			if (numl == 0 && numr == 0) {
				l = r;
				continue;
			}

			if (numl == 0 || numr == 0 || (numlr == 1 && numl == 1 && numr == 1)) {
				num[d]++;

				int cf = 0;
				int cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf++;
					}

					if ((x <= le[t] && wh[t][x - 1] + 1 != d)) {
						cf1++;
					}

					if (x <= cnt[t] - le[t]) {
						cf1++;
					}
				}

				dp[1][d] = add(mul(dp[1][d], cf1), mul(dp[0][d], cf));
				dp[0][d] = mul(dp[0][d], cf1);
			}
			else {
				num[d] += 2;

				ll cf = 0;
				ll cf1 = 0;

				for (int i = l; i < r; i++) {
					int x = g[i].second;
					int z = 0;

					if (x <= le[t] && x <= cnt[t] - le[t]) {
						z = 1;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 == d) {
						cf += numr - z;
					}

					if (x <= le[t] && wh[t][x - 1] + 1 != d) {
						cf1 += numr - z;
					}

					if (x <= cnt[t] - le[t]) {
						cf1 += numl - z;
					}
				}

				cf %= mod;
				cf1 %= mod;

				dp[1][d] = add(mul(dp[1][d], (int)cf1), mul(dp[0][d], (int)cf));
				dp[0][d] = mul(dp[0][d], (int)cf1);
			}

			l = r;
		}

		if (num[d] > numb) {
			numb = num[d];
			ans = dp[1][d];
		}
		else if (num[d] == numb) {
			ans = add(ans, dp[1][d]);
		}
	}

	cout << numb << ' ' << ans << endl;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC target ("avx2")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <climits>
#include <queue>
#include <deque>
using namespace std;
typedef long long li;
typedef long double ld;
const li MAX = 5005;
li inf = (li)1e13;
li n, m, cnt[MAX], revcnt[MAX], ind[MAX], revind[MAX], grass[MAX], ans[MAX];
li mod = (li)1e9 + 7;
vector<li> candys[MAX], l;
void push() {
	for (int i = 1; i <= n; i++) {
		while (ind[i] < candys[i].size() && candys[i][ind[i]] <= cnt[i]) ind[i]++;
		ind[i]--;
	}
	for (int i = 1; i <= n; i++) {
		while (revind[i] > 0 && candys[i][revind[i]] > revcnt[i]) revind[i]--;
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> grass[i];
		revcnt[grass[i]]++;
	}
	for (int i = 0; i <= n; i++) candys[i].push_back(0);
	for (int i = 0; i < m; i++) {
		li a, b;
		cin >> a >> b;
		candys[a].push_back(b);
	}
	li a = 1, sz = 0;
	for (int i = 1; i <= n; i++) {
		li cur = 0;
		while (cur < candys[i].size() && candys[i][cur] <= revcnt[i]) cur++;
		revind[i] = cur - 1;
		a *= max(li(1), cur - 1);
		a %= mod;
		if (cur - 1) sz++;
	}
	ans[sz] = a;
	for (int i = 1; i <= n; i++) {
		revcnt[grass[i]] --;
		cnt[grass[i]] ++;
		li tmpans = 1, sz = 0;
		push();
		if (cnt[grass[i]] != candys[grass[i]][ind[grass[i]]]) continue;
		else {
			for (int j = 1; j <= n; j++) {
				if (j != grass[i]) {
					if (ind[j] == 1 && revind[j] == 1) {
						sz++;
						tmpans *= 2;
					}
					else {
						li mini = min(ind[j], revind[j]);
						li maxi = max(ind[j], revind[j]);
						li t = 1;
						t = max(maxi - 1, li(1)) * max(mini, li(1));
						t %= mod;
						tmpans *= t;
						sz += min(li(1), ind[j]) + min(li(1), revind[j]);
					}
					tmpans %= mod;
				}
				else {
					sz += 1 + min(li(1), revind[j]);
					if (revind[j] == 1 && ind[j] == 1) sz--;
					tmpans *= max(li(1), revind[j] - 1);
					tmpans %= mod;
				}
			}
			ans[sz] += tmpans;
			ans[sz] %= mod;
		}
	}
	for (int i = n; i > 0; i--) {
		if (ans[i]) {
			cout << i << " " << ans[i] << "\n";
			return 0;
		}
	}
	cout << 0 << " " << 1 << "\n";
	return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC target ("avx2")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <climits>
#include <queue>
#include <deque>
using namespace std;
typedef long long li;
typedef long double ld;
const li MAX = 5005;
li inf = (li)1e13;
li n, m, cnt[MAX], revcnt[MAX], ind[MAX], revind[MAX], grass[MAX], ans[MAX];
li mod = 1000000007;
vector<li> candys[MAX], l;
void push() {
	for (int i = 1; i <= n; i++) {
		while (ind[i] < candys[i].size() && candys[i][ind[i]] <= cnt[i]) ind[i]++;
		ind[i]--;
	}
	for (int i = 1; i <= n; i++) {
		while (revind[i] > 0 && candys[i][revind[i]] > revcnt[i]) revind[i]--;
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> grass[i];
		revcnt[grass[i]]++;
	}
	for (int i = 0; i <= n; i++) candys[i].push_back(0);
	for (int i = 0; i < m; i++) {
		li a, b;
		cin >> a >> b;
		candys[a].push_back(b);
	}
	li a = 1, sz = 0;
	for (int i = 1; i <= n; i++) {
		li cur = 0;
		while (cur < candys[i].size() && candys[i][cur] <= revcnt[i]) cur++;
		cur--;
		if (cur != 0) {
			a *= cur;
			sz++;
			revind[i] = cur;
			a %= mod;
		}
	}
	ans[sz] = a;
	ans[sz] %= mod;
	for (int i = 1; i <= n; i++) {
		revcnt[grass[i]] --;
		cnt[grass[i]] ++;
		li tmpans = 1, sz = 0;
		push();
		if (cnt[grass[i]] != candys[grass[i]][ind[grass[i]]]) continue;
		else {
			for (int j = 1; j <= n; j++) {
				if (j != grass[i]) {
					if (ind[j] == 0 && revind[j] == 0) continue;
					if (ind[j] == 1 && revind[j] == 1) {
						sz++;
						tmpans *= 2;
					}
					else if (ind[j] != 0 && revind[j] == 0) {
						sz++;
						tmpans *= ind[j];
					}
					else if (ind[j] == 0 && revind[j] != 0) {
						sz++;
						tmpans *= revind[j];
					}
					else {
						sz += 2;
						li maxi = max(ind[j], revind[j]);
						li mini = min(ind[j], revind[j]);
						li t = (maxi - 1) * mini;
						t %= mod;
						tmpans *= t;
					}
					tmpans %= mod;
				}
				else {
					if (ind[j] == 0) while (1);
					if (revind[j] == 1) {
						sz++;
						if (ind[j] != 1) sz++;
					}
					else if (revind[j] == 0) {
						sz++;
					}
					else if (ind[j] > revind[j]) {
						sz += 2;
						tmpans *= revind[j];
					}
					else {
						sz += 2;
						tmpans *= (revind[j] - 1);
					}
					tmpans %= mod;
				}
			}
			ans[sz] += tmpans;
			ans[sz] %= mod;
		}
	}
	for (int i = n; i > 0; i--) {
		if (ans[i]) {
			cout << i << " " << ans[i] << "\n";
			return 0;
		}
	}
	cout << 0 << " " << 1 << "\n";
	return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC target ("avx2")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <climits>
#include <queue>
#include <deque>
using namespace std;
typedef long long li;
typedef long double ld;
const li MAX = 5005;
li inf = (li)1e13;
li n, m, cnt[MAX], revcnt[MAX], ind[MAX], revind[MAX], grass[MAX], ans[MAX];
li mod = (li)1e9 + 7;
vector<li> candys[MAX], l;
void push() {
	for (int i = 1; i <= n; i++) {
		while (ind[i] < candys[i].size() && candys[i][ind[i]] <= cnt[i]) ind[i]++;
		ind[i]--;
	}
	for (int i = 1; i <= n; i++) {
		while (revind[i] > 0 && candys[i][revind[i]] > revcnt[i]) revind[i]--;
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> grass[i];
		revcnt[grass[i]]++;
	}
	for (int i = 0; i <= n; i++) candys[i].push_back(0);
	for (int i = 0; i < m; i++) {
		li a, b;
		cin >> a >> b;
		candys[a].push_back(b);
	}
	li a = 1, sz = 0;
	for (int i = 1; i <= n; i++) {
		li cur = 0;
		while (cur < candys[i].size() && candys[i][cur] <= revcnt[i]) cur++;
		cur--;
		if (cur != 0) {
			a *= cur;
			sz++;
			revind[i] = cur;
			a %= mod;
		}
	}
	ans[sz] = a;
	ans[sz] %= mod;
	for (int i = 1; i <= n; i++) {
		revcnt[grass[i]] --;
		cnt[grass[i]] ++;
		li tmpans = 1, sz = 0;
		push();
		if (cnt[grass[i]] != candys[grass[i]][ind[grass[i]]]) continue;
		else {
			for (int j = 1; j <= n; j++) {
				if (j != grass[i]) {
					if (ind[j] == 0 && revind[j] == 0) continue;
					if (ind[j] == 1 && revind[j] == 1) {
						sz++;
						tmpans *= 2;
					}
					else if (ind[j] != 0 && revind[j] == 0) {
						sz++;
						tmpans *= ind[j];
					}
					else if (ind[j] == 0 && revind[j] != 0) {
						sz++;
						tmpans *= revind[j];
					}
					else {
						sz += 2;
						li maxi = max(ind[j], revind[j]);
						li mini = min(ind[j], revind[j]);
						li t = (maxi - 1) * mini;
						t %= mod;
						tmpans *= t;
					}
					tmpans %= mod;
				}
				else {
					if (revind[j] == 1) {
						sz++;
						if (ind[j] != 1) sz++;
					}
					else if (revind[j] == 0) {
						sz++;
					}
					else if (ind[j] > revind[j]) {
						sz += 2;
						tmpans *= revind[j];
					}
					else {
						sz += 2;
						tmpans *= (revind[j] - 1);
					}
					tmpans %= mod;
				}
			}
			ans[sz] += tmpans;
			ans[sz] %= mod;
		}
	}
	for (int i = n; i > 0; i--) {
		if (ans[i]) {
			cout << i << " " << ans[i] << "\n";
			return 0;
		}
	}
	cout << 0 << " " << 1 << "\n";
	return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC target ("avx2")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <climits>
#include <queue>
#include <deque>
using namespace std;
typedef long long li;
typedef long double ld;
const li MAX = 5005;
li inf = (li)1e13;
li n, m, cnt[MAX], revcnt[MAX], ind[MAX], revind[MAX], grass[MAX], ans[MAX];
li mod = (li)1e9 + 7;
vector<li> candys[MAX], l;
void push() {
	for (int i = 1; i <= n; i++) {
		while (ind[i] < candys[i].size() && candys[i][ind[i]] <= cnt[i]) ind[i]++;
		ind[i]--;
	}
	for (int i = 1; i <= n; i++) {
		while (revind[i] > 0 && candys[i][revind[i]] > revcnt[i]) revind[i]--;
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> grass[i];
		revcnt[grass[i]]++;
	}
	for (int i = 0; i <= n; i++) candys[i].push_back(0);
	for (int i = 0; i < m; i++) {
		li a, b;
		cin >> a >> b;
		candys[a].push_back(b);
	}
	li a = 1, sz = 0;
	for (int i = 1; i <= n; i++) {
		li cur = 0;
		while (cur < candys[i].size() && candys[i][cur] <= revcnt[i]) cur++;
		revind[i] = cur - 1;
		a *= max(li(1), cur - 1);
		a %= mod;
		if (cur - 1) sz++;
	}
	ans[sz] = a;
	for (int i = 1; i <= n; i++) {
		revcnt[grass[i]] --;
		cnt[grass[i]] ++;
		li tmpans = 1, sz = 0;
		push();
		if (cnt[grass[i]] != candys[grass[i]][ind[grass[i]]]) continue;
		else {
			for (int j = 1; j <= n; j++) {
				if (j != grass[i]) {
					if (ind[j] == 1 && revind[j] == 1) {
						sz++;
						tmpans *= 2;
					}
					else {
						li mini = min(ind[j], revind[j]);
						li maxi = max(ind[j], revind[j]);
						li t = 1;
						t = max(maxi - 1, li(1)) * max(mini, li(1));
						t %= mod;
						tmpans *= t;
						sz += min(li(1), ind[j]) + min(li(1), revind[j]);
					}
					tmpans %= mod;
				}
				else {
					sz += 1 + min(li(1), revind[j]);
					if (revind[j] == 1 && ind[j] == 1) sz--;
					if (ind[j] > revind[j]) tmpans *= max(li(1), revind[j]);
					else tmpans *= max(li(1), revind[j] - 1);
					tmpans %= mod;
				}
			}
			ans[sz] += tmpans;
			ans[sz] %= mod;
		}
	}
	for (int i = n; i > 0; i--) {
		if (ans[i]) {
			cout << i << " " << ans[i] << "\n";
			return 0;
		}
	}
	cout << 0 << " " << 1 << "\n";
	return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC target ("avx2")
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <set>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <climits>
#include <queue>
#include <deque>
using namespace std;
typedef long long li;
typedef long double ld;
const li MAX = 5005;
li inf = (li)1e13;
li n, m, cnt[MAX], revcnt[MAX], ind[MAX], revind[MAX], grass[MAX], ans[MAX];
li mod = (li)1e9 + 7;
vector<li> candys[MAX], l;
void push() {
	for (int i = 1; i <= n; i++) {
		while (ind[i] < candys[i].size() && candys[i][ind[i]] <= cnt[i]) ind[i]++;
		ind[i]--;
	}
	for (int i = 1; i <= n; i++) {
		while (revind[i] > 0 && candys[i][revind[i]] > revcnt[i]) revind[i]--;
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> grass[i];
		revcnt[grass[i]]++;
	}
	for (int i = 0; i <= n; i++) candys[i].push_back(0);
	for (int i = 0; i < m; i++) {
		li a, b;
		cin >> a >> b;
		candys[a].push_back(b);
	}
	li a = 1, sz = 0;
	for (int i = 1; i <= n; i++) {
		li cur = 0;
		while (cur < candys[i].size() && candys[i][cur] <= revcnt[i]) cur++;
		revind[i] = cur - 1;
		a *= max(li(1), cur - 1);
		a %= mod;
		if (cur - 1) sz++;
	}
	ans[sz] = a;
	for (int i = 1; i <= n; i++) {
		revcnt[grass[i]] --;
		cnt[grass[i]] ++;
		li tmpans = 1, sz = 0;
		push();
		if (cnt[grass[i]] != candys[grass[i]][ind[grass[i]]]) continue;
		else {
			for (int j = 1; j <= n; j++) {
				if (j != grass[i]) {
					if (ind[j] == 0 && revind[j] == 0) continue;
					if (ind[j] == 1 && revind[j] == 1) {
						sz++;
						tmpans *= 2;
					}
					else if (ind[j] != 0 && revind[j] == 0) {
						sz++;
						tmpans *= ind[j];
					}
					else if (ind[j] == 0 && revind[j] != 0) {
						sz++;
						tmpans *= revind[j];
					}
					else {
						sz += 2;
						li maxi = max(ind[j], revind[j]);
						li mini = min(ind[j], revind[j]);
						li t = (maxi - 1) * mini;
						t %= mod;
						tmpans *= t;
					}
					tmpans %= mod;
				}
				else {
					if (revind[j] == 1) {
						sz++;
						if (ind[j] != 1) sz++;
					}
					else if (revind[j] == 0) {
						sz++;
					}
					else if (ind[j] > revind[j]) {
						sz += 2;
						tmpans *= revind[j];
					}
					else {
						sz += 2;
						tmpans *= (revind[j] - 1);
					}
					tmpans %= mod;
				}
			}
			ans[sz] += tmpans;
			ans[sz] %= mod;
		}
	}
	for (int i = n; i > 0; i--) {
		if (ans[i]) {
			cout << i << " " << ans[i] << "\n";
			return 0;
		}
	}
	cout << 0 << " " << 1 << "\n";
	return 0;
}