//#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 (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], used[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);
	}
   for(int i = 0; i <= n; i++){
       sort(candys[i].begin(), candys[i].end());
   }
	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;
                        used[sz] = 1;
		}
	}
	for (int i = n; i > 0; i--) {
		if (used[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);
	}
   for(int i = 0; i <= n; i++){
       sort(candys[i].begin(), candys[i].end());
   }
	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;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

const int N = 5007;
const int M = 1e9 + 7;

int n, m, S[N], F[N], H[N], L[N], R[N], cnt[N], who[N];

map<PII, int> MP;

LL cnt2[N], cnt3[N], cnt4[N];

int main()
{
    _upgrade

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        cin >> S[i];

    for(int i = 1; i <= m; i++)
    {
        cin >> F[i] >> H[i];
        MP[{F[i], H[i]}] = i;
    }

    for(int i = 1; i <= n; i++)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
        {
            L[MP[{S[i], cnt[S[i]]}]] = i;
            who[i] = MP[{S[i], cnt[S[i]]}];
        }
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = n; i >= 1; i--)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
            R[MP[{S[i], cnt[S[i]]}]] = i;
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = 1; i <= m; i++)
    {
        if(L[i] == 0)
            L[i] = n + 1;

        if(R[i] == 0)
            R[i] = 0;

        //DBG(i, L[i], R[i]);
    }

    PLL ans = {0, 1};

    for(int i = 1; i <= m; i++)
    {
        if(1 <= R[i])
        {
            cnt4[F[i]]++;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(cnt4[i] > 0)
        {
            ans.first++;
            ans.second = ans.second * cnt4[i] % M;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        PLL tmp = {1, 1};
        int id = who[i];

        if(who[i] != 0)
        {

            LL cnt5 = 0;

            for(int j = 1; j <= m; j++)
            {
                if(F[id] == F[j])
                {
                    if(id != j && i < R[j])
                        cnt5++;
                }
            }

            if(cnt5 > 0)
            {
                tmp.first++;
                tmp.second = cnt5;
            }

            for(int j = 1; j <= n; j++)
            {
                if(F[id] == j) continue;

                if(cnt2[j] + cnt3[j] + cnt4[j] == 0)
                    continue;

                LL ways = 0;
                ways = cnt3[j] * cnt4[j] % M;
                ways = (ways + (cnt3[j] + cnt4[j]) * cnt2[j]) % M;
                ways = (ways + cnt2[j] * (cnt2[j] - 1)) % M;

                if(ways != 0)
                {
                    tmp.first += 2;
                    tmp.second = tmp.second * ways % M;
                }
                else
                {
                    tmp.first++;
                    tmp.second = tmp.second * (2LL * cnt2[j] + cnt3[j] + cnt4[j]) % M;
                }
            }

        }

        for(int j = 1; j <= m; j++)
        {
            if(L[j] < R[j])
            {
                if(R[j] == i)
                {
                    cnt2[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(L[j] == i)
                {
                    cnt2[F[j]]++;
                    cnt4[F[j]]--;
                }
            }
            else
            {
                if(R[j] == i && L[j] == i)
                {
                    cnt4[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(R[j] == i)
                {
                    cnt4[F[j]]--;
                }
                else if(L[j] == i)
                {
                    cnt3[F[j]]++;
                }
            }
        }

        if(who[i] != 0)
        {
            if(tmp.first > ans.first)
                ans = tmp;
            else if(tmp.first == ans.first)
                ans.second = (ans.second + tmp.second) % M;
        }
    }

    cout << ans.first << " " << ans.second << "\n";

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

const int N = 5007;
const int M = 1e9 + 7;

int n, m, S[N], F[N], H[N], L[N], R[N], cnt[N], who[N];

map<PII, int> MP;

LL cnt2[N], cnt3[N], cnt4[N];

int main()
{
    _upgrade

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        cin >> S[i];

    for(int i = 1; i <= m; i++)
    {
        cin >> F[i] >> H[i];
        MP[{F[i], H[i]}] = i;
    }

    for(int i = 1; i <= n; i++)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
        {
            L[MP[{S[i], cnt[S[i]]}]] = i;
            who[i] = MP[{S[i], cnt[S[i]]}];
        }
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = n; i >= 1; i--)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
            R[MP[{S[i], cnt[S[i]]}]] = i;
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = 1; i <= m; i++)
    {
        if(L[i] == 0)
            L[i] = n + 1;

        if(R[i] == 0)
            R[i] = 0;
    }

    PLL ans = {0, 1};

    for(int i = 1; i <= m; i++)
    {
        if(1 <= R[i])
        {
            cnt4[F[i]]++;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(cnt4[i] > 0)
        {
            ans.first++;
            ans.second = ans.second * cnt4[i] % M;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(who[i] == 0) continue;

        PLL tmp = {1, 1};

        int id = who[i];

        LL cnt5 = 0;

        for(int j = 1; j <= m; j++)
        {
            if(F[id] == F[j])
            {
                if(id != j && i < R[j])
                    cnt5++;
                continue;
            }
        }

        if(cnt5 > 0)
        {
            tmp.first++;
            tmp.second = cnt5;
        }

        for(int j = 1; j <= n; j++)
        {
            if(F[id] == j) continue;

            if(cnt2[j] + cnt3[j] + cnt4[j] == 0)
                continue;

            if(cnt2[j] == 1 && cnt3[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (2LL * tmp.second) % M;
            }
            else if(cnt2[j] + cnt3[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt4[j]) % M;
            }
            else if(cnt2[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt3[j]) % M;
            }
            else
            {
                tmp.first += 2;

                LL ways = 0;
                ways = cnt3[j] * cnt4[j] % M;
                ways = (ways + (cnt3[j] + cnt4[j]) * cnt2[j]) % M;
                ways = (ways + cnt2[j] * (cnt2[j] - 1)) % M;

                tmp.second = tmp.second * ways % M;
            }
        }

        for(int j = 1; j <= m; j++)
        {
            if(L[j] < R[j])
            {
                if(R[j] == i)
                {
                    cnt2[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(L[j] == i)
                {
                    cnt2[F[j]]++;
                    cnt4[F[j]]--;
                }
            }
            else
            {
                if(R[j] == i && L[j] == i)
                {
                    cnt4[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(R[j] == i)
                {
                    cnt4[F[j]]--;
                }
                else if(L[j] == i)
                {
                    cnt3[F[j]]++;
                }
            }
        }

        assert(tmp.second != 0);

        if(tmp.first > ans.first)
            ans = tmp;
        else if(tmp.first == ans.first)
            ans.second = (ans.second + tmp.second) % M;
    }

    cout << ans.first << " " << ans.second << "\n";

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

const int N = 5007;
const int M = 1e9 + 7;

int n, m, S[N], F[N], H[N], L[N], R[N], cnt[N], who[N];

map<PII, int> MP;

LL cnt2[N], cnt3[N], cnt4[N];

int main()
{
    _upgrade

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        cin >> S[i];

    for(int i = 1; i <= m; i++)
    {
        cin >> F[i] >> H[i];
        MP[{F[i], H[i]}] = i;
    }

    for(int i = 1; i <= n; i++)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
        {
            L[MP[{S[i], cnt[S[i]]}]] = i;
            who[i] = MP[{S[i], cnt[S[i]]}];
        }
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = n; i >= 1; i--)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
            R[MP[{S[i], cnt[S[i]]}]] = i;
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = 1; i <= m; i++)
    {
        if(L[i] == 0)
            L[i] = n + H[i];

        if(R[i] == 0)
            R[i] = -H[i];
    }

    PLL ans = {0, 1};

    for(int i = 1; i <= m; i++)
    {
        if(1 <= R[i])
        {
            cnt4[F[i]]++;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(cnt4[i] > 0)
        {
            ans.first++;
            ans.second = ans.second * cnt4[i] % M;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(who[i] == 0) continue;

        PLL tmp = {1, 1};

        int id = who[i];

        LL cnt5 = 0;

        for(int j = 1; j <= m; j++)
        {
            if(F[id] == F[j])
            {
                if(id != j && i < R[j])
                    cnt5++;
                continue;
            }
        }

        if(cnt5 > 0)
        {
            tmp.first++;
            tmp.second = cnt5;
        }

        for(int j = 1; j <= n; j++)
        {
            if(F[id] == j) continue;

            if(cnt2[j] + cnt3[j] + cnt4[j] == 0)
                continue;

            if(cnt2[j] == 1 && cnt3[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (2LL * tmp.second) % M;
            }
            else if(cnt2[j] + cnt3[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt4[j]) % M;
            }
            else if(cnt2[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt3[j]) % M;
            }
            else
            {
                tmp.first += 2;
                LL ways = 1;
                ways = cnt3[j] * cnt4[j] % M;
                ways = (ways + (cnt3[j] + cnt4[j]) * cnt2[j]) % M;
                ways = (ways + cnt2[j] * (cnt2[j] - 1)) % M;

                tmp.second = tmp.second * ways % M;
            }
        }

        for(int j = 1; j <= m; j++)
        {
            if(L[j] < R[j])
            {
                if(R[j] == i)
                {
                    cnt2[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(L[j] == i)
                {
                    cnt2[F[j]]++;
                    cnt4[F[j]]--;
                }
            }
            else
            {
                if(R[j] == i && L[j] == i)
                {
                    cnt4[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(R[j] == i)
                {
                    cnt4[F[j]]--;
                }
                else if(L[j] == i)
                {
                    cnt3[F[j]]++;
                }
            }
        }

        if(tmp.first > ans.first)
            ans = tmp;
        else
            ans.second = (ans.second + tmp.second) % M;
    }

    cout << ans.first << " " << ans.second << "\n";

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

const int N = 5007;
const int M = 1e9 + 7;

int n, m, S[N], F[N], H[N], L[N], R[N], cnt[N], who[N];

map<PII, int> MP;

LL cnt2[N], cnt3[N], cnt4[N];

int main()
{
    _upgrade

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        cin >> S[i];

    for(int i = 1; i <= m; i++)
    {
        cin >> F[i] >> H[i];
        MP[{F[i], H[i]}] = i;
    }

    for(int i = 1; i <= n; i++)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
        {
            L[MP[{S[i], cnt[S[i]]}]] = i;
            who[i] = MP[{S[i], cnt[S[i]]}];
        }
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = n; i >= 1; i--)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
            R[MP[{S[i], cnt[S[i]]}]] = i;
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = 1; i <= m; i++)
    {
        if(L[i] == 0)
            L[i] = n + H[i];

        if(R[i] == 0)
            R[i] = -H[i];
    }

    PLL ans = {0, 1};

    for(int i = 1; i <= m; i++)
    {
        if(1 <= R[i])
        {
            cnt4[F[i]]++;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(cnt4[i] > 0)
        {
            ans.first++;
            ans.second = ans.second * cnt4[i] % M;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(who[i] == 0) continue;

        PLL tmp = {1, 1};

        int id = who[i];

        LL cnt5 = 0;

        for(int j = 1; j <= m; j++)
        {
            if(F[id] == F[j])
            {
                if(id != j && i < R[j])
                    cnt5++;
                continue;
            }
        }

        if(cnt5 > 0)
        {
            tmp.first++;
            tmp.second = cnt5;
        }

        for(int j = 1; j <= n; j++)
        {
            if(F[id] == j) continue;

            if(cnt2[j] + cnt3[j] + cnt4[j] == 0)
                continue;

            if(cnt2[j] == 1 && cnt3[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (2LL * tmp.second) % M;
            }
            else if(cnt2[j] + cnt3[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt4[j]) % M;
            }
            else if(cnt2[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt3[j]) % M;
            }
            else
            {
                tmp.first += 2;

                LL ways = 1;
                ways = cnt3[j] * cnt4[j] % M;
                ways = (ways + (cnt3[j] + cnt4[j]) * cnt2[j]) % M;
                ways = (ways + cnt2[j] * (cnt2[j] - 1)) % M;

                tmp.second = tmp.second * ways % M;
            }
        }

        for(int j = 1; j <= m; j++)
        {
            if(L[j] < R[j])
            {
                if(R[j] == i)
                {
                    cnt2[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(L[j] == i)
                {
                    cnt2[F[j]]++;
                    cnt4[F[j]]--;
                }
            }
            else
            {
                if(R[j] == i && L[j] == i)
                {
                    cnt4[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(R[j] == i)
                {
                    cnt4[F[j]]--;
                }
                else if(L[j] == i)
                {
                    cnt3[F[j]]++;
                }
            }
        }

        if(tmp.first > ans.first)
            ans = tmp;
        else if(tmp.first == ans.first)
            ans.second = (ans.second + tmp.second) % M;
    }

    cout << ans.first << " " << ans.second << "\n";

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

const int N = 5007;
const int M = 1e9 + 7;

LL pw2[N];

int n, m, S[N], F[N], H[N], L[N], R[N], cnt[N], who[N];

map<PII, int> MP;

LL cnt2[N], cnt3[N], cnt4[N];

int main()
{
    _upgrade

    pw2[0] = 1;
    for(int i = 1; i < N; i++)
        pw2[i] = 2LL * pw2[i - 1] % M;

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        cin >> S[i];

    for(int i = 1; i <= m; i++)
    {
        cin >> F[i] >> H[i];
        MP[{F[i], H[i]}] = i;
    }

    for(int i = 1; i <= n; i++)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
        {
            L[MP[{S[i], cnt[S[i]]}]] = i;
            who[i] = MP[{S[i], cnt[S[i]]}];
        }
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = n; i >= 1; i--)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
            R[MP[{S[i], cnt[S[i]]}]] = i;
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = 1; i <= m; i++)
    {
        if(L[i] == 0)
            L[i] = n + H[i];

        if(R[i] == 0)
            R[i] = -H[i];
    }

    PLL ans = {0, 1};

    for(int i = 1; i <= m; i++)
    {
        if(1 <= R[i])
        {
            cnt4[F[i]]++;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(cnt4[i] > 0)
        {
            ans.first++;
            ans.second = ans.second * cnt4[i] % M;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(who[i] == 0) continue;

        PLL tmp = {1, 1};

        int id = who[i];

        LL cnt5 = 0;

        for(int j = 1; j <= m; j++)
        {
            if(F[id] == F[j])
            {
                if(id != j && i < R[j])
                    cnt5++;
                continue;
            }
        }

        if(cnt5 > 0)
        {
            tmp.first++;
            tmp.second = cnt5;
        }

        for(int j = 1; j <= n; j++)
        {
            if(F[id] == j) continue;

            if(cnt2[j] + cnt3[j] + cnt4[j] == 0)
                continue;

            if(cnt2[j] == 1 && cnt3[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (2LL * tmp.second) % M;
            }
            else if(cnt2[j] + cnt3[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt4[j]) % M;
            }
            else if(cnt2[j] + cnt4[j] == 0)
            {
                tmp.first++;
                tmp.second = (tmp.second * cnt3[j]) % M;
            }
            else
            {
                tmp.first += 2;
                LL ways = 1;
                ways = cnt3[j] * cnt4[j] % M;
                ways = (ways + (cnt3[j] + cnt4[j]) * cnt2[j]) % M;
                ways = (ways + cnt2[j] * (cnt2[j] - 1) / 2) % M;

                tmp.second = tmp.second * ways % M;
            }
        }

        for(int j = 1; j <= m; j++)
        {
            if(L[j] < R[j])
            {
                if(R[j] == i)
                {
                    cnt2[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(L[j] == i)
                {
                    cnt2[F[j]]++;
                    cnt4[F[j]]--;
                }
            }
            else
            {
                if(R[j] == i && L[j] == i)
                {
                    cnt4[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(R[j] == i)
                {
                    cnt4[F[j]]--;
                }
                else if(L[j] == i)
                {
                    cnt3[F[j]]++;
                }
            }
        }

        if(tmp.first > ans.first)
            ans = tmp;
        else
            ans.second = (ans.second + tmp.second) % M;
    }

    cout << ans.first << " " << ans.second << "\n";

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

const int N = 5007;
const int M = 1e9 + 7;

int n, m, S[N], F[N], H[N], L[N], R[N], cnt[N], who[N];

map<PII, int> MP;

LL cnt2[N], cnt3[N], cnt4[N];

int main()
{
    _upgrade

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        cin >> S[i];

    for(int i = 1; i <= m; i++)
    {
        cin >> F[i] >> H[i];
        MP[{F[i], H[i]}] = i;
    }

    for(int i = 1; i <= n; i++)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
        {
            L[MP[{S[i], cnt[S[i]]}]] = i;
            who[i] = MP[{S[i], cnt[S[i]]}];
        }
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = n; i >= 1; i--)
    {
        cnt[S[i]]++;
        if(MP.find({S[i], cnt[S[i]]}) != MP.end())
            R[MP[{S[i], cnt[S[i]]}]] = i;
    }

    for(int i = 1; i <= n; i++)
        cnt[i] = 0;

    for(int i = 1; i <= m; i++)
    {
        if(L[i] == 0)
            L[i] = n + 1;

        if(R[i] == 0)
            R[i] = 0;
    }

    PLL ans = {0, 1};

    for(int i = 1; i <= m; i++)
    {
        if(1 <= R[i])
        {
            cnt4[F[i]]++;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(cnt4[i] > 0)
        {
            ans.first++;
            ans.second = ans.second * cnt4[i] % M;
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(who[i] == 0) continue;

        PLL tmp = {1, 1};

        int id = who[i];

        LL cnt5 = 0;

        for(int j = 1; j <= m; j++)
        {
            if(F[id] == F[j])
            {
                if(id != j && i < R[j])
                    cnt5++;
                continue;
            }
        }

        if(cnt5 > 0)
        {
            tmp.first++;
            tmp.second = cnt5;
        }

        for(int j = 1; j <= n; j++)
        {
            if(F[id] == j) continue;

            if(cnt2[j] + cnt3[j] + cnt4[j] == 0)
                continue;

            LL ways = 0;
            ways = cnt3[j] * cnt4[j] % M;
            ways = (ways + (cnt3[j] + cnt4[j]) * cnt2[j]) % M;
            ways = (ways + cnt2[j] * (cnt2[j] - 1)) % M;

            if(ways != 0)
            {
                tmp.first += 2;
                tmp.second = tmp.second * ways % M;
            }
            else
            {
                tmp.first++;
                tmp.second = tmp.second * (2LL * cnt2[j] + cnt3[j] + cnt4[j]) % M;
            }
        }

        for(int j = 1; j <= m; j++)
        {
            if(L[j] < R[j])
            {
                if(R[j] == i)
                {
                    cnt2[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(L[j] == i)
                {
                    cnt2[F[j]]++;
                    cnt4[F[j]]--;
                }
            }
            else
            {
                if(R[j] == i && L[j] == i)
                {
                    cnt4[F[j]]--;
                    cnt3[F[j]]++;
                }
                else if(R[j] == i)
                {
                    cnt4[F[j]]--;
                }
                else if(L[j] == i)
                {
                    cnt3[F[j]]++;
                }
            }
        }

        if(tmp.first > ans.first)
            ans = tmp;
        else if(tmp.first == ans.first)
            ans.second = (ans.second + tmp.second) % M;
    }

    cout << ans.first << " " << ans.second << "\n";

	return 0;
}


#include "bits/stdc++.h"
using namespace std;

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i,s,e) for(ll i=s;i<=ll(e);++i)
#define DEC(i,s,e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (5006)
int n, m, A[MAXN], f[MAXN], h[MAXN], send[MAXN];
vector<int> v[MAXN],ppl[MAXN];
bitset<MAXN>bad;
ll ans,ways,mod=1e9+7;
#define gc getchar
void in(int &x){
	x=0;
	char ch=gc();
	while(ch<'0'||ch>'9') ch=gc();
	while(ch>='0'&&ch<='9') {
		x=(x<<3)+(x<<1)+ch-48;
		ch=gc();
	}
}
int main()
{
	FAST
	in(n),in(m);
	FOR(i,1,n)in(A[i]);
	FOR(i,1,m)in(f[i]),in(h[i]);
	FOR(i,1,n)v[A[i]].pb(i);
	FOR(i,1,m)if(v[f[i]].size()<=h[i]-1)bad[i]=1;
	FOR(i,1,m)if(!bad[i])ppl[f[i]].pb(i);
	FOR(i,1,n)sort(all(ppl[i]),[](ll x,ll y){return h[x]<h[y];});
	auto frt=[&](ll x) {
		assert(!bad[x]);
		return v[f[x]][h[x]-1];
	};
	auto bck=[&](ll x){
		assert(!bad[x]);
		return v[f[x]][siz(v[f[x]])-h[x]];
	};
	ans=-INF;
	FOR(i,1,m)if(!bad[i]){
		ll line=frt(i); mmst(send,0);
		ll mx = 1, sum = 1;
		FOR(j,1,n) if(ppl[j].size()) {
			if(j^f[i]) {
				if(ppl[j].size()==1){
					if(frt(ppl[j][0]) < line || bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				} else {
					auto grr=[&](ll a,ll b){
						if(frt(a) < line && bck(b) > line) return 2;
						if(bck(a) > line && frt(b) < line) return 2;
						if(frt(a) < line || bck(a) > line) return 1;
						return 0;
					};
					send[j]=grr(ppl[j][0], ppl[j][1]), mx+=send[j];
				}
			} else {
				if(ppl[j][0]==i){
					if(ppl[j].size()>1 && bck(ppl[j][1]) > line) ++ mx, send[j]=1;
				} else {
					if(ppl[j].size() && bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				}
			}
		}
		if(mx<ans) continue;
		FOR(j,1,n) if(send[j]) {
			if(j^f[i]) {
				ll num=0;
				if(send[j]==1){
					for(auto k:ppl[j]) num+=(frt(k)<line)+(bck(k)>line);
				} else if(send[j]==2) {
					ll canf=0, canb=0;
					for(auto k:ppl[j]) canf+=frt(k)<line, canb+=bck(k)>line;
					for(auto k:ppl[j]){
						canf-=frt(k)<line, canb-=bck(k)>line;
						if(bck(k)>line) num += canf;
						if(frt(k)<line) num += canb;
						canf+=frt(k)<line, canb+=bck(k)>line;
					}
					num>>=1;
				} else assert(0);
				sum*=num,sum%=mod;
			} else { assert(send[j]==1);
				ll num=0;
				for(auto k:ppl[j]) if(k!=i && bck(k)>line) ++ num;
				if(num==0)num=1;
				sum*=num,sum%=mod;
			}
		}
		if(mx>ans)ans=mx,ways=sum; else ways+=sum,ways%=mod;
	}
	// try another case where everyone back, basically everyone's who elligible although no 2 of same f[i]
	ll mx=0, sum=1;
	FOR(i,1,n)if(ppl[i].size())++mx;
	FOR(i,1,n)if(ppl[i].size())sum*=siz(ppl[i]),sum%=mod;
	if(mx>ans) ans=mx, ways=sum;
	else if(mx==ans) ways+=sum,ways%=mod;
	cout<<ans<<' '<<ways<<'\n';
}


#include "bits/stdc++.h"
using namespace std;

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i,s,e) for(ll i=s;i<=ll(e);++i)
#define DEC(i,s,e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (5006)
ll n, m, A[MAXN], f[MAXN], h[MAXN], send[MAXN];
vector<ll> v[MAXN];
deque<ll> ppl[MAXN];
bitset<MAXN>bad;
ll ans,ways,mod=1e9+7;
int main()
{
	FAST
	cin>>n>>m;
	FOR(i,1,n)cin>>A[i];
	FOR(i,1,m)cin>>f[i]>>h[i];
	FOR(i,1,n)v[A[i]].pb(i);
	FOR(i,1,m)ppl[f[i]].pb(i);
	FOR(i,1,m)if(v[f[i]].size()<=h[i]-1)bad[i]=1;
	FOR(i,1,m)if(bad[i])ppl[f[i]].erase(find(all(ppl[f[i]]),i));
	FOR(i,1,n)sort(all(ppl[i]),[](ll x,ll y){return h[x]<h[y];});
	auto frt=[&](ll x) {
		assert(!bad[x]);
		return v[f[x]][h[x]-1];
	};
	auto bck=[&](ll x){
		assert(!bad[x]);
		return v[f[x]][siz(v[f[x]])-h[x]];
	};
	ans=-LLINF;
	FOR(i,1,m)if(!bad[i]){
		ll line=frt(i); mmst(send,0);
		ll mx = 1, sum = 1;
		FOR(j,1,n) if(ppl[j].size()) {
			if(j^f[i]) {
				if(ppl[j].size()==1){
					if(frt(ppl[j][0]) < line || bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				} else {
					auto grr=[&](ll a,ll b){
						if(frt(a) < line && bck(b) > line) return 2;
						if(bck(a) > line && frt(b) < line) return 2;
						if(frt(a) < line || bck(a) > line) return 1;
						return 0;
					};
					send[j]=grr(ppl[j][0], ppl[j][1]), mx+=send[j];
				}
			} else {
				bool jy=0; if(ppl[j][0]==i) jy=1, ppl[j].pop_front();
				if(ppl[j].size() && bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				if(jy) ppl[j].push_front(i);
			}
		}
		if(mx<ans) continue;
		FOR(j,1,n) if(send[j]) {
			if(j^f[i]) {
				ll num=0;
				if(send[j]==1){
					for(auto k:ppl[j]) num+=(frt(k)<line)+(bck(k)>line);
				} else if(send[j]==2) {
					ll canf=0, canb=0;
					for(auto k:ppl[j]) canf+=frt(k)<line, canb+=bck(k)>line;
					for(auto k:ppl[j]){
						canf-=frt(k)<line, canb-=bck(k)>line;
						if(bck(k)>line) num += canf, num %= mod;
						if(frt(k)<line) num += canb, num %= mod;
						canf+=frt(k)<line, canb+=bck(k)>line;
					}
					assert(num&1^1), num/=2;
				} else assert(0);
				sum*=num,sum%=mod;
			} else { assert(send[j]==1);
				ll num=0;
				bool jy=0; if(ppl[j][0]==i) jy=1, ppl[j].pop_front();
				for(auto k:ppl[j]) if(bck(k)>line) ++ num;
				if(jy) ppl[j].push_front(i);
				sum*=num,sum%=mod;
			}
		}
		if(mx>ans)ans=mx,ways=sum; else ways+=sum,ways%=mod;
	}
	// try another case where everyone back, basically everyone's who elligible although no 2 of same f[i]
	ll mx=0, sum=1;
	FOR(i,1,n)if(ppl[i].size())++mx;
	FOR(i,1,n)if(ppl[i].size())sum*=siz(ppl[i]),sum%=mod;
	if(mx>ans) ans=mx, ways=sum;
	else if(mx==ans) ways+=sum;
	cout<<ans<<' '<<ways<<'\n';
}


#include "bits/stdc++.h"
using namespace std;

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i,s,e) for(ll i=s;i<=ll(e);++i)
#define DEC(i,s,e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (5006)
ll n, m, A[MAXN], f[MAXN], h[MAXN], send[MAXN];
vector<ll> v[MAXN];
deque<ll> ppl[MAXN];
bitset<MAXN>bad;
ll ans,ways,mod=1e9+7;
int main()
{
	FAST
	cin>>n>>m;
	FOR(i,1,n)cin>>A[i];
	FOR(i,1,m)cin>>f[i]>>h[i];
	FOR(i,1,n)v[A[i]].pb(i);
	FOR(i,1,m)ppl[f[i]].pb(i);
	FOR(i,1,m)if(v[f[i]].size()<=h[i]-1)bad[i]=1;
	FOR(i,1,m)if(bad[i])ppl[f[i]].erase(find(all(ppl[f[i]]),i));
	FOR(i,1,n)sort(all(ppl[i]),[](ll x,ll y){return h[x]<h[y];});
	auto frt=[&](ll x) {
		assert(!bad[x]);
		return v[f[x]][h[x]-1];
	};
	auto bck=[&](ll x){
		assert(!bad[x]);
		return v[f[x]][siz(v[f[x]])-h[x]];
	};
	ans=-LLINF;
	FOR(i,1,m)if(!bad[i]){
		ll line=frt(i); mmst(send,0);
		ll mx = 1, sum = 1;
		FOR(j,1,n) if(ppl[j].size()) {
			if(j^f[i]) {
				if(ppl[j].size()==1){
					if(frt(ppl[j][0]) < line || bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				} else {
					auto grr=[&](ll a,ll b){
						if(frt(a) < line && bck(b) > line) return 2;
						if(bck(a) > line && frt(b) < line) return 2;
						if(frt(a) < line || bck(a) > line) return 1;
						return 0;
					};
					send[j]=grr(ppl[j][0], ppl[j][1]), mx+=send[j];
				}
			} else {
				bool jy=0; if(ppl[j][0]==i) jy=1, ppl[j].pop_front();
				if(ppl[j].size() && bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				if(jy) ppl[j].push_front(i);
			}
		}
		if(mx<ans) continue;
		FOR(j,1,n) if(send[j]) {
			if(j^f[i]) {
				ll num=0;
				if(send[j]==1){
					for(auto k:ppl[j]) num+=(frt(k)<line)+(bck(k)>line);
				} else if(send[j]==2) {
					ll canf=0, canb=0;
					for(auto k:ppl[j]) canf+=frt(k)<line, canb+=bck(k)>line;
					for(auto k:ppl[j]){
						canf-=frt(k)<line, canb-=bck(k)>line;
						if(bck(k)>line) num += canf, num %= mod;
						if(frt(k)<line) num += canb, num %= mod;
						canf+=frt(k)<line, canb+=bck(k)>line;
					}
					assert(num&1^1), num/=2;
				} else assert(0);
				sum*=num,sum%=mod;
			} else { assert(send[j]==1);
				ll num=0;
				for(auto k:ppl[j]) if(k!=i && bck(k)>line) ++ num;
				if(num==0)num=1;
				sum*=num,sum%=mod;
			}
		}
		if(mx>ans)ans=mx,ways=sum; else ways+=sum,ways%=mod;
	}
	// try another case where everyone back, basically everyone's who elligible although no 2 of same f[i]
	ll mx=0, sum=1;
	FOR(i,1,n)if(ppl[i].size())++mx;
	FOR(i,1,n)if(ppl[i].size())sum*=siz(ppl[i]),sum%=mod;
	if(mx>ans) ans=mx, ways=sum;
	else if(mx==ans) ways+=sum,ways%=mod;
	cout<<ans<<' '<<ways<<'\n';
}


#include "bits/stdc++.h"
using namespace std;

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i,s,e) for(ll i=s;i<=ll(e);++i)
#define DEC(i,s,e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (5006)
int n, m, A[MAXN], f[MAXN], h[MAXN], send[MAXN];
vector<int> v[MAXN],ppl[MAXN];
bitset<MAXN>bad;
ll ans,ways,mod=1e9+7;
#define gc _getchar_nolock
void in(int &x){
	x=0;
	char ch=gc();
	while(ch<'0'||ch>'9') ch=gc();
	while(ch>='0'&&ch<='9') {
		x=(x<<3)+(x<<1)+ch-48;
		ch=gc();
	}
}
int main()
{
	FAST
	in(n),in(m);
	FOR(i,1,n)in(A[i]);
	FOR(i,1,m)in(f[i]),in(h[i]);
	FOR(i,1,n)v[A[i]].pb(i);
	FOR(i,1,m)ppl[f[i]].pb(i);
	FOR(i,1,m)if(v[f[i]].size()<=h[i]-1)bad[i]=1;
	FOR(i,1,m)if(bad[i])ppl[f[i]].erase(find(all(ppl[f[i]]),i));
	FOR(i,1,n)sort(all(ppl[i]),[](ll x,ll y){return h[x]<h[y];});
	auto frt=[&](ll x) {
		assert(!bad[x]);
		return v[f[x]][h[x]-1];
	};
	auto bck=[&](ll x){
		assert(!bad[x]);
		return v[f[x]][siz(v[f[x]])-h[x]];
	};
	ans=-INF;
	FOR(i,1,m)if(!bad[i]){
		ll line=frt(i); mmst(send,0);
		ll mx = 1, sum = 1;
		FOR(j,1,n) if(ppl[j].size()) {
			if(j^f[i]) {
				if(ppl[j].size()==1){
					if(frt(ppl[j][0]) < line || bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				} else {
					auto grr=[&](ll a,ll b){
						if(frt(a) < line && bck(b) > line) return 2;
						if(bck(a) > line && frt(b) < line) return 2;
						if(frt(a) < line || bck(a) > line) return 1;
						return 0;
					};
					send[j]=grr(ppl[j][0], ppl[j][1]), mx+=send[j];
				}
			} else {
				if(ppl[j][0]==i){
					if(ppl[j].size()>1 && bck(ppl[j][1]) > line) ++ mx, send[j]=1;
				} else {
					if(ppl[j].size() && bck(ppl[j][0]) > line) ++ mx, send[j]=1;
				}
			}
		}
		if(mx<ans) continue;
		FOR(j,1,n) if(send[j]) {
			if(j^f[i]) {
				ll num=0;
				if(send[j]==1){
					for(auto k:ppl[j]) num+=(frt(k)<line)+(bck(k)>line);
				} else if(send[j]==2) {
					ll canf=0, canb=0;
					for(auto k:ppl[j]) canf+=frt(k)<line, canb+=bck(k)>line;
					for(auto k:ppl[j]){
						canf-=frt(k)<line, canb-=bck(k)>line;
						if(bck(k)>line) num += canf;
						if(frt(k)<line) num += canb;
						canf+=frt(k)<line, canb+=bck(k)>line;
					}
					num>>=1;
				} else assert(0);
				sum*=num,sum%=mod;
			} else { assert(send[j]==1);
				ll num=0;
				for(auto k:ppl[j]) if(k!=i && bck(k)>line) ++ num;
				if(num==0)num=1;
				sum*=num,sum%=mod;
			}
		}
		if(mx>ans)ans=mx,ways=sum; else ways+=sum,ways%=mod;
	}
	// try another case where everyone back, basically everyone's who elligible although no 2 of same f[i]
	ll mx=0, sum=1;
	FOR(i,1,n)if(ppl[i].size())++mx;
	FOR(i,1,n)if(ppl[i].size())sum*=siz(ppl[i]),sum%=mod;
	if(mx>ans) ans=mx, ways=sum;
	else if(mx==ans) ways+=sum,ways%=mod;
	cout<<ans<<' '<<ways<<'\n';
}


/**********************************### With The name of Allah ###***********************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<bitset>
#define ll long long
#define MAX(x,y) x>y?x:y
#define MIN(x,y) x<y?x:y
//int SET(int n,int i) {return (n|(1<<i));}
//int RESET(int n,int i) {return (n&~(1<<i));}
//bool check(int n,int i) {return (n&(1<<i));}
using namespace std;
// To test time Complexity just declare Time veriable in begining of main().
//class Timer {
//    clock_t start;
//    string name;
//public:
//    Timer() {name = "";start = clock();}
//    Timer(string s){name = s;start = clock();}
//    ~Timer() {fprintf(stderr, "%s: %.3gs\n", name.c_str(), 1.0*(clock() - start) / CLOCKS_PER_SEC);}
//};

// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 5005
const int MOD = 1e9+7;
ll sweetness[MX], h[MX], fev[MX];
vector<ll> loca[MX];
struct myst{
	ll fev, leftt, rightt;
	myst(){}
	myst(ll lft, ll rgt, ll fevv){
		leftt = lft;
		rightt = rgt;
		fev =fevv;
	}
};
vector<myst> all;
ll fall_l[MX], fall_r[MX], both_s[MX];

void input_fun()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>sweetness[i];
		loca[sweetness[i]].push_back(i);
	}
	for(int i=0;i<m;i++){
		cin>>fev[i]>>h[i];
		if(h[i] > (ll)loca[fev[i]].size()){
			continue;
		}
		all.push_back(myst(loca[fev[i]][h[i]-1], loca[fev[i]][loca[fev[i]].size()-h[i]], fev[i]));
	}
	int siz = all.size();
	if(siz == 0){
		cout<<"0 1"<<endl;
		return;
	}
	if(siz == 1){
		cout<<"1 2"<<endl;
		return;
	}
	sort(all.begin(), all.end(), [&](myst a, myst b){
		return a.leftt < b.leftt;
	});
	all.push_back(myst(-1, 0, 0));
	ll slp_c = 0, f_ways = 0;
	for(int k=0;k<siz+1;k++){
		ll i = all[k].leftt;
		for(int j=0;j<=n;j++) both_s[j]=fall_l[j]=fall_r[j] = 0;
		for(int j=0;j<siz;j++){
			if(k == j)continue;
			ll fev = all[j].fev;
			ll lft = all[j].leftt;
			ll rgt = all[j].rightt;
			if(all[k].fev == fev){
				if(all[k].leftt < all[j].rightt) fall_r[fev]++;
				continue;
			}
			if(lft < i && rgt > i){
				both_s[fev]++;
			}
			else if(lft < i){
				fall_l[fev]++;
			}
			else if(rgt > i){
				fall_r[fev]++;
			}
		}
		ll sleep = (k<siz), ways = 1;
		for(int j=0;j<=n;j++){
			if(both_s[j] == 0 && fall_l[j] == 0 && fall_r[j] == 0)continue;
			if(j == i){
				if(fall_r[j])sleep++, ways = ways*fall_r[j]%MOD;
				continue;
			}
			if(both_s[j]==0 && fall_l[j]==0){
				sleep++;
				ways = (ways*fall_r[j])%MOD;
			}
			else if(both_s[j]==0 && fall_r[j]==0){
				sleep++;
				ways = (ways*fall_l[j])%MOD;
			}
			else if(both_s[j]==1&&fall_l[j]==0&&fall_r[j]==0){
				sleep++;
				ways = ways*2%MOD;
			}
			else{
				sleep+=2;
				ll ww = fall_l[j]*fall_r[j]%MOD;
				ww += both_s[j]*fall_l[j]%MOD;
				ww += both_s[j]*fall_r[j]%MOD;
				ww += both_s[j]*(both_s[j]-1)%MOD;
				ways = (ways*ww)%MOD;
			}
		}
		//cout<<i<<": slp: "<<sleep<<" ways: "<<ways<<endl;
		if(slp_c == sleep) f_ways = (f_ways+ways)%MOD;
		else if(slp_c < sleep) slp_c = sleep, f_ways = ways;
	}
	cout<<slp_c<<" "<<f_ways<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define ss(x) (int) x.size()
#define fi first
#define se second
#define cat(x) cerr << #x << " = " << x << endl
#define rep(i, j, n) for (int i = j; i <= n; ++i)
#define per(i, j, n) for (int i = n; j <= i; --i)
#define all(x) x.begin(), x.end()

using namespace std;

pair<int,int> ask(int x) {
	printf ("+ %d\n", x);
	fflush(stdout);
	int a, b;
	scanf ("%d%d", &a, &b);
	return {a,b};
}

int qw(int x) {
	int q = 0;
	while (q * (q - 1) / 2 < x) q++;
	return q;
}

int n, A, B, res[111];

int main() {
	scanf ("%d", &n);
	scanf ("%d%d", &A, &B);
	auto q1 = ask(1);
	auto q2 = ask(2);
	auto q3 = ask(3);
	auto q4 = ask(1);

	// 1.
	res[1] = qw(q4.fi - q3.fi) - 1;
	// 3.
	if (q3.fi - q2.fi > 0) res[3] = qw(q3.fi - q2.fi);
	else res[3] = (q2.se - q1.se == 0 ? 0 : 1);
	// 2.
	int ilo = q4.se - q3.se;
	res[2] = ilo / (res[3] + 1) - 1;

	int magic = q3.se - q2.se;
	int last1 = q4.fi;
	int last2 = q4.se;

	rep(i, 4, n - 1) {
		auto q = ask(i);
		magic -= (res[i - 2] + 1) * (res[i - 3] + 1);
		if (q.fi != last1) res[i] = qw(q.fi - last1);
		else res[i] = (magic == 0 ? 0 : 1);
		magic = q.se - last2;
		last1 = q.fi;
		last2 = q.se;
	}
	magic -= (res[n - 2] + 1) * (res[n - 3] + 1);
	res[n] = magic / (res[n - 2] + 1);

	printf ("!");
	rep(i, 1, n) printf (" %d", res[i]);
	printf ("\n");
	fflush(stdout);

	return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define ss(x) (int) x.size()
#define fi first
#define se second
#define cat(x) cerr << #x << " = " << x << endl
#define rep(i, j, n) for (int i = j; i <= n; ++i)
#define per(i, j, n) for (int i = n; j <= i; --i)
#define all(x) x.begin(), x.end()

using namespace std;

pair<int,int> ask(int x) {
	printf ("? %d\n", x);
	fflush(stdout);
	int a, b;
	scanf ("%d%d", &a, &b);
	return {a,b};
}

int qw(int x) {
	int q = 0;
	while (q * (q - 1) / 2 < x) q++;
	return q;
}

int n, A, B, res[111];

int main() {
	scanf ("%d", &n);
	scanf ("%d%d", &A, &B);
	auto q1 = ask(1);
	auto q2 = ask(2);
	auto q3 = ask(3);
	auto q4 = ask(1);

	// 1.
	res[1] = qw(q4.fi - q3.fi) - 1;
	// 3.
	if (q3.fi - q2.fi > 0) res[3] = qw(q3.fi - q2.fi);
	else res[3] = (q2.se - q1.se == 0 ? 0 : 1);
	// 2.
	int ilo = q4.se - q3.se;
	res[2] = ilo / (res[3] + 1) - 1;

	int magic = q3.se - q2.se;
	int last1 = q4.fi;
	int last2 = q4.se;

	rep(i, 4, n - 1) {
		auto q = ask(i);
		magic -= (res[i - 2] + 1) * (res[i - 3] + 1);
		if (q.fi != last1) res[i] = qw(q.fi - last1);
		else res[i] = (magic == 0 ? 0 : 1);
		magic = q.se - last2;
		last1 = q.fi;
		last2 = q.se;
	}
	magic -= (res[n - 2] + 1) * (res[n - 3] + 1);
	res[n] = magic / (res[n - 2] + 1);

	printf ("!");
	rep(i, 1, n) printf (" %d", res[i]);
	printf ("\n");
	fflush(stdout);

	return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define ss(x) (int) x.size()
#define fi first
#define se second
#define cat(x) cerr << #x << " = " << x << endl
#define rep(i, j, n) for (int i = j; i <= n; ++i)
#define per(i, j, n) for (int i = n; j <= i; --i)
#define all(x) x.begin(), x.end()

using namespace std;

pair<int,int> ask(int x) {
	printf ("+ %d\n", x);
	fflush(stdout);
	int a, b;
	scanf ("%d%d", &a, &b);
	return {a,b};
}

int qw(int x) {
	int q = 0;
	while (q * (q - 1) / 2 < x) q++;
	return q;
}

int n, A, B, res[111];

int main() {
	scanf ("%d", &n);
	scanf ("%d%d", &A, &B);
	auto q1 = ask(1);
	auto q2 = ask(2);
	auto q3 = ask(3);
	auto q4 = ask(1);

	// 1.
	res[1] = qw(q4.fi - q3.fi) - 1;
	if (res[1] < 0) res[1] = 0;
	// 3.
	if (q3.fi - q2.fi > 0) res[3] = qw(q3.fi - q2.fi);
	else res[3] = (q2.se - q1.se == 0 ? 0 : 1);
	// 2.
	int ilo = q4.se - q3.se;
	res[2] = ilo / (res[3] + 1) - 1;

	int magic = q3.se - q2.se;
	int last1 = q4.fi;
	int last2 = q4.se;

	rep(i, 4, n - 1) {
		auto q = ask(i);
		magic -= (res[i - 2] + 1) * (res[i - 3] + 1);
		if (q.fi != last1) res[i] = qw(q.fi - last1);
		else res[i] = (magic == 0 ? 0 : 1);
		magic = q.se - last2;
		last1 = q.fi;
		last2 = q.se;
	}
	magic -= (res[n - 2] + 1) * (res[n - 3] + 1);
	res[n] = magic / (res[n - 2] + 1);

	printf ("!");
	rep(i, 1, n) printf (" %d", res[i]);
	printf ("\n");
	fflush(stdout);

	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <numeric>
#include <algorithm>
#include <bitset>
#include <complex>
#include <array>
#include <list>
#include <stack>
#include <valarray>

using namespace std;

typedef unsigned uint;
typedef long long Int;
typedef unsigned long long UInt;

const int INF = 1001001001;
const Int INFLL = 1001001001001001001LL;

template<typename T> void pv(T a, T b) { for (T i = a; i != b; ++i) cout << *i << " "; cout << endl; }
template<typename T> void chmin(T& a, T b) { if (a > b) a = b; }
template<typename T> void chmax(T& a, T b) { if (a < b) a = b; }
int in() { int x; scanf("%d", &x); return x; }
double fin() { double x; scanf("%lf", &x); return x; }
Int lin() { Int x; scanf("%lld", &x); return x; }

// #define LOCAL

int n;
int ko, sy;

int correct[111], cur[111];

pair<int, int> calc() {
  int k = 0, s = 0;
  for (int i = 0; i < n; ++i) {
    k += cur[i] * (cur[i] - 1) * (cur[i] - 2) / 6;
  }
  for (int i = 0; i < n - 2; ++i) {
    s += cur[i] * cur[i + 1] * cur[i + 2];
  }
  return make_pair(k, s);
}

pair<int, int> ins(int k) {
#ifdef LOCAL
  ++cur[k];
  pair<int, int> r2 = calc();
  pair<int, int> res(r2.first - ko, r2.second - sy);
  ko = r2.first;
  sy = r2.second;
  return res;
#else
  printf("+ %d\n", k + 1);
  fflush(stdout);
  int ko2 = in();
  int sy2 = in();
  pair<int, int> res(ko2 - ko, sy2 - sy);
  ko = ko2;
  sy = sy2;
  return res;
#endif
}

int f_ko(int dif) {
  for (int t = 1; ; ++t) {
    const int k1 = t * (t - 1) * (t - 2) / 6;
    const int k2 = (t + 1) * t * (t - 1) / 6;
    if (k2 - k1 == dif) {
      return t + 1;
    }
  }
}

pair<int, int> qrs[111];
int as[111];

int val(int k, int kk) {
  if (k % 2 == kk % 2) {
    return as[kk] + (k > kk ? 1 : 0);
  } else {
    return as[kk] + (k % 2 == 1 ? 1 : 0);
  }
}

int qvalue(int k) {
  int res = 0;
  if (k - 2 >= 0) res += val(k, k - 2) * val(k, k - 1);
  if (k - 1 >= 0 && k + 1 < n) res += val(k, k - 1) * val(k, k + 1);
  if (k + 2 < n) res += val(k, k + 1) * val(k, k + 2);
  return res;
}

bool so_rec(int fr, int to) {
  if (to - fr <= 8) {
    vector<int> zos;
    for (int i = fr; i < to; ++i) {
      if (qrs[i].first != 0) {
        as[i] = f_ko(qrs[i].first) - 1;
      } else {
        zos.push_back(i);
      }
    }

    bool found = false;
    int ans = 0;
    const int m = zos.size();
    for (int z = 0; z < (1<<m); ++z) {
      for (int i = 0; i < m; ++i) {
        if (z & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      bool ok = true;
      for (int i = fr - 2; i < to + 2; ++i) {
        if (0 <= i && i < n) {
          ok &= qvalue(i) == qrs[i].second;
        }
      }
      if (ok) {
        if (found) {
          return false;
        } else {
          found = true;
          ans = z;
        }
      }
    }

    if (found) {
      for (int i = 0; i < m; ++i) {
        if (ans & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  int k = to + (fr - to) / 2 - 2;
  vector<int> zos;
  for (int i = k; i < k + 4; ++i) {
    if (qrs[i].first != 0) {
      as[i] = f_ko(qrs[i].first) - 1;
    } else {
      zos.push_back(i);
    }
  }

  bool found = false;
  vector<int> ans_o(to - fr);
  const int m = zos.size();
  for (int z = 0; z < (1<<m); ++z) {
    for (int i = 0; i < m; ++i) {
      if (z & (1 << i)) {
        as[zos[i]] = 1;
      } else {
        as[zos[i]] = 0;
      }
    }
    if (so_rec(fr, k) && so_rec(k + 4, to)) {
      if (found) {
        return false;
      } else {
        found = true;
        for (int i = fr; i < to; ++i) {
          ans_o[i - fr] = as[i];
        }
      }
    }
  }

  if (found) {
    for (int i = fr; i < to; ++i) {
      as[i] = ans_o[i - fr];
    }
    return true;
  } else {
    return false;
  }
}

vector<int> solve_odd() {
  for (int i = 0, t = 0; i < n; ++i) {
    qrs[t] = ins(t);
    t += 2;
    if (t >= n) {
      t = 1;
    }
  }

  assert(so_rec(0, n));

  vector<int> res;
  for (int i = 0; i < n; ++i) {
    res.push_back(as[i]);
  }
  return res;
}

vector<int> solve_4() {
  vector<pair<int, int>> qr;
  for (int i = 0; i < n; ++i) {
    qr.push_back(ins(i % 3));
  }

  vector<int> res(4, -1);
  res[0] = f_ko(qr[3].first) - 2;
  if (qr[1].first != 0) {
    res[1] = f_ko(qr[1].first) - 1;
  }
  if (qr[2].first != 0) {
    res[2] = f_ko(qr[2].first) - 1;
  }
  if (res[1] >= 0 || res[2] >= 0) {
    if (res[1] < 0) res[1] = qr[3].second / (res[2] + 1) - 1;
    if (res[2] < 0) res[2] = qr[3].second / (res[1] + 1) - 1;
  } else {
    if (qr[3].second == 1) {
      res[1] = res[2] = 0;
    } else if (qr[3].second == 4) {
      res[1] = res[2] = 1;
    } else {
      if (qr[1].second == 0) {
        res[1] = 1; res[2] = 0;
      } else {
        res[1] = 0; res[2] = 1;
      }
    }
  }
  res[3] = qr[2].second / (res[1] + 1) - (res[0] + 1);

  return res;
}

int main() {
  n = in();
#ifdef LOCAL
  for (int i = 0; i < n; ++i) {
    cur[i] = correct[i] = in();
  }
  auto t = calc();
  ko = t.first;
  sy = t.second;
#else
  ko = in();
  sy = in();
#endif

  vector<int> res = n == 4 ? solve_4() : solve_odd();

  printf("!");
  for (const int a : res) {
    printf(" %d", a);
  }
  puts("");
  fflush(stdout);

#ifdef LOCAL
  for (int i = 0; i < n; ++i) {
    if (res[i] != correct[i]) {
      puts("WA");
      return 0;
    }
  }
  puts("AC");
#endif

  return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <numeric>
#include <algorithm>
#include <bitset>
#include <complex>
#include <array>
#include <list>
#include <stack>
#include <valarray>

using namespace std;

typedef unsigned uint;
typedef long long Int;
typedef unsigned long long UInt;

const int INF = 1001001001;
const Int INFLL = 1001001001001001001LL;

template<typename T> void pv(T a, T b) { for (T i = a; i != b; ++i) cout << *i << " "; cout << endl; }
template<typename T> void chmin(T& a, T b) { if (a > b) a = b; }
template<typename T> void chmax(T& a, T b) { if (a < b) a = b; }
int in() { int x; scanf("%d", &x); return x; }
double fin() { double x; scanf("%lf", &x); return x; }
Int lin() { Int x; scanf("%lld", &x); return x; }

int n;
int ko, sy;

int correct[111], cur[111];

pair<int, int> calc() {
  int k = 0, s = 0;
  for (int i = 0; i < n; ++i) {
    k += cur[i] * (cur[i] - 1) * (cur[i] - 2) / 6;
  }
  for (int i = 0; i < n - 2; ++i) {
    s += cur[i] * cur[i + 1] * cur[i + 2];
  }
  return make_pair(k, s);
}

pair<int, int> ins(int k) {
  ++cur[k];
  pair<int, int> r2 = calc();
  pair<int, int> res(r2.first - ko, r2.second - sy);
  ko = r2.first;
  sy = r2.second;
  return res;
  // printf("+ %d\n", k + 1);
  // fflush(stdout);
  // int ko2 = in();
  // int sy2 = in();
  // pair<int, int> res(ko2 - ko, sy2 - sy);
  // ko = ko2;
  // sy = sy2;
  // return res;
}

int f_ko(int dif) {
  for (int t = 2; ; ++t) {
    const int k1 = t * (t - 1) * (t - 2) / 6;
    const int k2 = (t + 1) * t * (t - 1) / 6;
    if (k2 - k1 == dif) {
      return t + 1;
    }
  }
}

// vector<int> solve_even() {
//   vector<pair<int, int>> qr;
//   for (int i = 0; i < n; ++i) {
//     qr.push_back(ins((2 * i + 1) % n));
//   }

//   vector<int> res(n);
//   for (int i = 0; i < n / 2; ++i) {
//     res[2 * i] = f_ko(qr[n / 2 + i].first) - 2;
//   }

//   for (int i = 1; i < n; i += 2) {
//     // i-1: a[i-3]''*a[i-2] + a[i-2]*a[i] + a[i]*a[i+1]'
//     int b = res[i - 1];
//     if (i - 3 >= 0) b -= (res[i - 3] + 2) * res[i - 2];
//     res[i] = b / (res[i - 2] + (i + 1 < n ? (res[i + 1] + 1) : 0));
//   }

//   return res;
// }

pair<int, int> qrs[111];
int as[111];

int qvalue(int k) {
  int res = 0;
  if (k - 2 >= 0) res += (as[k - 2] + 1) * (as[k - 1] + 1);
  if (k - 1 >= 0 && k + 1 < n) res += (as[k - 1] + 1) * as[k + 1];
  if (k + 2 < n) res += as[k + 1] * as[k + 2];
  return res;
}

bool so_rec(int fr, int to) {
  if (to - fr <= 8) {
    vector<int> zos;
    for (int i = fr; i < to; ++i) {
      if (qrs[i].first != 0) {
        as[i] = f_ko(qrs[i].first) - 1;
      } else {
        zos.push_back(i);
      }
    }

    bool found = false;
    int ans = 0;
    const int m = zos.size();
    for (int z = 0; z < (1<<m); ++z) {
      for (int i = 0; i < m; ++i) {
        if (z & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      bool ok = true;
      for (int i = fr - 2; i < to + 2; ++i) {
        if (0 <= i && i < n) {
          ok &= qvalue(i) == qrs[i].second;
        }
      }
      if (ok) {
        if (found) {
          return false;
        } else {
          found = true;
          ans = z;
        }
      }
    }

    if (found) {
      for (int i = 0; i < m; ++i) {
        if (ans & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  int k = to + (fr - to) / 2 - 2;
  vector<int> zos;
  for (int i = k; i < k + 4; ++i) {
    if (qrs[i].first != 0) {
      as[i] = f_ko(qrs[i].first) - 1;
    } else {
      zos.push_back(i);
    }
  }

  bool found = false;
  vector<int> ans_o(to - fr);
  const int m = zos.size();
  for (int z = 0; z < (1<<m); ++z) {
    for (int i = 0; i < m; ++i) {
      if (z & (1 << i)) {
        as[zos[i]] = 1;
      } else {
        as[zos[i]] = 0;
      }
    }
    if (so_rec(fr, k) && so_rec(k + 4, to)) {
      if (found) {
        return false;
      } else {
        found = true;
        for (int i = fr; i < to; ++i) {
          ans_o[i - fr] = as[i];
        }
      }
    }
  }

  if (found) {
    for (int i = fr; i < to; ++i) {
      as[i] = ans_o[i - fr];
    }
    return true;
  } else {
    return false;
  }
}

vector<int> solve_odd() {
  vector<pair<int, int>> qr;
  for (int i = 0; i < n; ++i) {
    qrs[i] = ins(i);
  }

  assert(so_rec(0, n));

  vector<int> res;
  for (int i = 0; i < n; ++i) {
    res.push_back(as[i]);
  }
  return res;
}

int main() {
  n = in();
  for (int i = 0; i < n; ++i) {
    cur[i] = correct[i] = in();
  }
  auto t = calc();
  ko = t.first;
  sy = t.second;
  // ko = in();
  // sy = in();

  vector<int> res = solve_odd();
  // if (n % 2 == 0) {
  //   res = solve_odd();
  // } else {
  //   res = solve_odd();
  // }

  printf("!");
  for (const int a : res) {
    printf(" %d", a);
  }
  puts("");
  fflush(stdout);

  for (int i = 0; i < n; ++i) {
    if (res[i] != correct[i]) {
      puts("WA");
      return 0;
    }
  }
  puts("AC");

  return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <numeric>
#include <algorithm>
#include <bitset>
#include <complex>
#include <array>
#include <list>
#include <stack>
#include <valarray>

using namespace std;

typedef unsigned uint;
typedef long long Int;
typedef unsigned long long UInt;

const int INF = 1001001001;
const Int INFLL = 1001001001001001001LL;

template<typename T> void pv(T a, T b) { for (T i = a; i != b; ++i) cout << *i << " "; cout << endl; }
template<typename T> void chmin(T& a, T b) { if (a > b) a = b; }
template<typename T> void chmax(T& a, T b) { if (a < b) a = b; }
int in() { int x; scanf("%d", &x); return x; }
double fin() { double x; scanf("%lf", &x); return x; }
Int lin() { Int x; scanf("%lld", &x); return x; }

int n;
int ko, sy;

int correct[111], cur[111];

pair<int, int> calc() {
  int k = 0, s = 0;
  for (int i = 0; i < n; ++i) {
    k += cur[i] * (cur[i] - 1) * (cur[i] - 2) / 6;
  }
  for (int i = 0; i < n - 2; ++i) {
    s += cur[i] * cur[i + 1] * cur[i + 2];
  }
  return make_pair(k, s);
}

pair<int, int> ins(int k) {
  // ++cur[k];
  // pair<int, int> r2 = calc();
  // pair<int, int> res(r2.first - ko, r2.second - sy);
  // ko = r2.first;
  // sy = r2.second;
  // return res;
  printf("+ %d\n", k + 1);
  fflush(stdout);
  int ko2 = in();
  int sy2 = in();
  pair<int, int> res(ko2 - ko, sy2 - sy);
  ko = ko2;
  sy = sy2;
  return res;
}

int f_ko(int dif) {
  for (int t = 2; ; ++t) {
    const int k1 = t * (t - 1) * (t - 2) / 6;
    const int k2 = (t + 1) * t * (t - 1) / 6;
    if (k2 - k1 == dif) {
      return t + 1;
    }
  }
}

pair<int, int> qrs[111];
int as[111];

int qvalue(int k) {
  int res = 0;
  if (k - 2 >= 0) res += (as[k - 2] + 1) * (as[k - 1] + 1);
  if (k - 1 >= 0 && k + 1 < n) res += (as[k - 1] + 1) * as[k + 1];
  if (k + 2 < n) res += as[k + 1] * as[k + 2];
  return res;
}

bool so_rec(int fr, int to) {
  if (to - fr <= 8) {
    vector<int> zos;
    for (int i = fr; i < to; ++i) {
      if (qrs[i].first != 0) {
        as[i] = f_ko(qrs[i].first) - 1;
      } else {
        zos.push_back(i);
      }
    }

    bool found = false;
    int ans = 0;
    const int m = zos.size();
    for (int z = 0; z < (1<<m); ++z) {
      for (int i = 0; i < m; ++i) {
        if (z & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      bool ok = true;
      for (int i = fr - 2; i < to + 2; ++i) {
        if (0 <= i && i < n) {
          ok &= qvalue(i) == qrs[i].second;
        }
      }
      if (ok) {
        if (found) {
          return false;
        } else {
          found = true;
          ans = z;
        }
      }
    }

    if (found) {
      for (int i = 0; i < m; ++i) {
        if (ans & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  int k = to + (fr - to) / 2 - 2;
  vector<int> zos;
  for (int i = k; i < k + 4; ++i) {
    if (qrs[i].first != 0) {
      as[i] = f_ko(qrs[i].first) - 1;
    } else {
      zos.push_back(i);
    }
  }

  bool found = false;
  vector<int> ans_o(to - fr);
  const int m = zos.size();
  for (int z = 0; z < (1<<m); ++z) {
    for (int i = 0; i < m; ++i) {
      if (z & (1 << i)) {
        as[zos[i]] = 1;
      } else {
        as[zos[i]] = 0;
      }
    }
    if (so_rec(fr, k) && so_rec(k + 4, to)) {
      if (found) {
        return false;
      } else {
        found = true;
        for (int i = fr; i < to; ++i) {
          ans_o[i - fr] = as[i];
        }
      }
    }
  }

  if (found) {
    for (int i = fr; i < to; ++i) {
      as[i] = ans_o[i - fr];
    }
    return true;
  } else {
    return false;
  }
}

vector<int> solve_odd() {
  vector<pair<int, int>> qr;
  for (int i = 0; i < n; ++i) {
    qrs[i] = ins(i);
  }

  assert(so_rec(0, n));

  vector<int> res;
  for (int i = 0; i < n; ++i) {
    res.push_back(as[i]);
  }
  return res;
}

int main() {
  n = in();
  // for (int i = 0; i < n; ++i) {
  //   cur[i] = correct[i] = in();
  // }
  // auto t = calc();
  // ko = t.first;
  // sy = t.second;
  ko = in();
  sy = in();

  vector<int> res = solve_odd();
  // if (n % 2 == 0) {
  //   res = solve_odd();
  // } else {
  //   res = solve_odd();
  // }

  printf("!");
  for (const int a : res) {
    printf(" %d", a);
  }
  puts("");
  fflush(stdout);

  // for (int i = 0; i < n; ++i) {
  //   if (res[i] != correct[i]) {
  //     puts("WA");
  //     return 0;
  //   }
  // }
  // puts("AC");

  return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <numeric>
#include <algorithm>
#include <bitset>
#include <complex>
#include <array>
#include <list>
#include <stack>
#include <valarray>

using namespace std;

typedef unsigned uint;
typedef long long Int;
typedef unsigned long long UInt;

const int INF = 1001001001;
const Int INFLL = 1001001001001001001LL;

template<typename T> void pv(T a, T b) { for (T i = a; i != b; ++i) cout << *i << " "; cout << endl; }
template<typename T> void chmin(T& a, T b) { if (a > b) a = b; }
template<typename T> void chmax(T& a, T b) { if (a < b) a = b; }
int in() { int x; scanf("%d", &x); return x; }
double fin() { double x; scanf("%lf", &x); return x; }
Int lin() { Int x; scanf("%lld", &x); return x; }

int n;
int ko, sy;

int correct[111], cur[111];

pair<int, int> calc() {
  int k = 0, s = 0;
  for (int i = 0; i < n; ++i) {
    k += cur[i] * (cur[i] - 1) * (cur[i] - 2) / 6;
  }
  for (int i = 0; i < n - 2; ++i) {
    s += cur[i] * cur[i + 1] * cur[i + 2];
  }
  return make_pair(k, s);
}

pair<int, int> ins(int k) {
  // ++cur[k];
  // pair<int, int> r2 = calc();
  // pair<int, int> res(r2.first - ko, r2.second - sy);
  // ko = r2.first;
  // sy = r2.second;
  // return res;
  printf("+ %d\n", k + 1);
  fflush(stdout);
  int ko2 = in();
  int sy2 = in();
  pair<int, int> res(ko2 - ko, sy2 - sy);
  ko = ko2;
  sy = sy2;
  return res;
}

int f_ko(int dif) {
  for (int t = 1; ; ++t) {
    const int k1 = t * (t - 1) * (t - 2) / 6;
    const int k2 = (t + 1) * t * (t - 1) / 6;
    if (k2 - k1 == dif) {
      return t + 1;
    }
  }
}

pair<int, int> qrs[111];
int as[111];

int qvalue(int k) {
  int res = 0;
  if (k - 2 >= 0) res += (as[k - 2] + 1) * (as[k - 1] + 1);
  if (k - 1 >= 0 && k + 1 < n) res += (as[k - 1] + 1) * as[k + 1];
  if (k + 2 < n) res += as[k + 1] * as[k + 2];
  return res;
}

bool so_rec(int fr, int to) {
  if (to - fr <= 8) {
    vector<int> zos;
    for (int i = fr; i < to; ++i) {
      if (qrs[i].first != 0) {
        as[i] = f_ko(qrs[i].first) - 1;
      } else {
        zos.push_back(i);
      }
    }

    bool found = false;
    int ans = 0;
    const int m = zos.size();
    for (int z = 0; z < (1<<m); ++z) {
      for (int i = 0; i < m; ++i) {
        if (z & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      bool ok = true;
      for (int i = fr - 2; i < to + 2; ++i) {
        if (0 <= i && i < n) {
          ok &= qvalue(i) == qrs[i].second;
        }
      }
      if (ok) {
        if (found) {
          return false;
        } else {
          found = true;
          ans = z;
        }
      }
    }

    if (found) {
      for (int i = 0; i < m; ++i) {
        if (ans & (1 << i)) {
          as[zos[i]] = 1;
        } else {
          as[zos[i]] = 0;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  int k = to + (fr - to) / 2 - 2;
  vector<int> zos;
  for (int i = k; i < k + 4; ++i) {
    if (qrs[i].first != 0) {
      as[i] = f_ko(qrs[i].first) - 1;
    } else {
      zos.push_back(i);
    }
  }

  bool found = false;
  vector<int> ans_o(to - fr);
  const int m = zos.size();
  for (int z = 0; z < (1<<m); ++z) {
    for (int i = 0; i < m; ++i) {
      if (z & (1 << i)) {
        as[zos[i]] = 1;
      } else {
        as[zos[i]] = 0;
      }
    }
    if (so_rec(fr, k) && so_rec(k + 4, to)) {
      if (found) {
        return false;
      } else {
        found = true;
        for (int i = fr; i < to; ++i) {
          ans_o[i - fr] = as[i];
        }
      }
    }
  }

  if (found) {
    for (int i = fr; i < to; ++i) {
      as[i] = ans_o[i - fr];
    }
    return true;
  } else {
    return false;
  }
}

vector<int> solve_odd() {
  for (int i = 0; i < n; ++i) {
    qrs[i] = ins(i);
  }

  assert(so_rec(0, n));

  vector<int> res;
  for (int i = 0; i < n; ++i) {
    res.push_back(as[i]);
  }
  return res;
}

vector<int> solve_4() {
  vector<pair<int, int>> qr;
  for (int i = 0; i < n; ++i) {
    qr.push_back(ins(i % 3));
  }

  vector<int> res(4, -1);
  res[0] = f_ko(qr[3].first) - 2;
  if (qr[1].first != 0) {
    res[1] = f_ko(qr[1].first) - 1;
  }
  if (qr[2].first != 0) {
    res[2] = f_ko(qr[2].first) - 1;
  }
  if (res[1] >= 0 || res[2] >= 0) {
    if (res[1] < 0) res[1] = qr[3].second / (res[2] + 1) - 1;
    if (res[2] < 0) res[2] = qr[3].second / (res[1] + 1) - 1;
  } else {
    if (qr[3].second == 1) {
      res[1] = res[2] = 0;
    } else if (qr[3].second == 4) {
      res[1] = res[2] = 1;
    } else {
      if (qr[1].second == 0) {
        res[1] = 1; res[2] = 0;
      } else {
        res[1] = 0; res[2] = 1;
      }
    }
  }
  res[3] = qr[2].second / (res[1] + 1) - (res[0] + 1);

  return res;
}

int main() {
  n = in();
  // for (int i = 0; i < n; ++i) {
  //   cur[i] = correct[i] = in();
  // }
  // auto t = calc();
  // ko = t.first;
  // sy = t.second;
  ko = in();
  sy = in();

  vector<int> res = n == 4 ? solve_4() : solve_odd();
  // if (n % 2 == 0) {
  //   res = solve_odd();
  // } else {
  //   res = solve_odd();
  // }

  printf("!");
  for (const int a : res) {
    printf(" %d", a);
  }
  puts("");
  fflush(stdout);

  // for (int i = 0; i < n; ++i) {
  //   if (res[i] != correct[i]) {
  //     puts("WA");
  //     return 0;
  //   }
  // }
  // puts("AC");

  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define ll long long
#define ull unsigned long long
#define ld long double
#define pii pair <int, int>
#define pll pair <ll, ll>
#define pci pair <char, int>
#define pld pair <ld, ld>
#define ppld pair <pld, pld>
#define ppll pair <pll, pll>
#define pldl pair <ld, ll>
#define vll vector <ll>
#define vvll vector <vll>
#define vpll vector <pll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define mll map <ll, ll>
#define fastmap gp_hash_table
#define cd complex <double>
#define vcd vector <cd>
#define PI 3.14159265358979
#define ordered_set tree <ll, null_type, less <ll>, rb_tree_tag, tree_order_statistics_node_update>
#pragma 03
using namespace std;
using namespace __gnu_pbds;
ll n, s1, s2, t1, t2, d1[105], d2[105], a[105];
int main(){
	cin >> n >> s1 >> s2;
	for (ll i = n - 1; i >= 0; i--){
		cout << "+ ";
		if (i > 2) cout << i << endl;
		else cout << i % 2 + 1 << endl;
		t1 = s1, t2 = s2; cin >> s1 >> s2;
		d1[i] = s1 - t1, d2[i] = s2 - t2;
	}
	a[0] = sqrt(d1[0] * 2);
	a[2] = d2[0] - d2[2] - 1;
	a[1] = d2[2] / (a[2] + 1);
	a[3] = d2[1] / (a[2] + 1) - a[0] - 2;
	for (ll i = 4; i < n; i++) a[i] = (d2[i - 1] - a[i - 4] * a[i - 3]) / (a[i - 1] + 1) - a[i - 3] - 1;
	a[n - 1]++;
	for (ll i = 0; i < n; i++) cout << a[i] << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define ll long long
#define ull unsigned long long
#define ld long double
#define pii pair <int, int>
#define pll pair <ll, ll>
#define pci pair <char, int>
#define pld pair <ld, ld>
#define ppld pair <pld, pld>
#define ppll pair <pll, pll>
#define pldl pair <ld, ll>
#define vll vector <ll>
#define vvll vector <vll>
#define vpll vector <pll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define mll map <ll, ll>
#define fastmap gp_hash_table
#define cd complex <double>
#define vcd vector <cd>
#define PI 3.14159265358979
#define ordered_set tree <ll, null_type, less <ll>, rb_tree_tag, tree_order_statistics_node_update>
#pragma 03
using namespace std;
using namespace __gnu_pbds;
ll n, s1, s2, t1, t2, d1[105], d2[105], a[105];
int main(){
	cin >> n >> s1 >> s2;
	for (ll i = n - 1; i >= 0; i--){
		cout << "+ ";
		if (i > 2) cout << i << endl;
		else cout << i % 2 + 1 << endl;
		t1 = s1, t2 = s2; cin >> s1 >> s2;
		d1[i] = s1 - t1, d2[i] = s2 - t2;
	}
	a[0] = sqrt(d1[0] * 2);
	a[2] = d2[0] - d2[2] - 1;
	a[1] = d2[2] / (a[2] + 1);
	a[3] = d2[1] / (a[2] + 1) - a[0] - 2;
	for (ll i = 4; i < n; i++) a[i] = (d2[i - 1] - a[i - 4] * a[i - 3]) / (a[i - 1] + 1) - a[i - 3] - 1;
	a[n - 1]++;
	cout << "! ";
	for (ll i = 0; i < n; i++) cout << a[i] << " ";
}


#include <bits/stdc++.h>
#define PB push_back
#define ST first
#define ND second
#define _ ios_base::sync_with_stdio(0); cin.tie(0);
#define debug 0
//mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

using namespace std;

using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;

const int nax = 110;
int n;
int ans[nax];
int add[nax];
pair<ll,ll>track[nax], delta[nax];
int inv[100*100*100],p[nax];
int id;

int hidden[nax];

int rand(int a,int b) {
	return a + (rand()%(b-a+1));
}

void query(int x) {
	if(!debug) {
		cout << "+ " << x << "\n";
		add[x]++;
		fflush(stdout);
		pair<ll,ll>w;
		cin >> w.ST >> w.ND;
		id++;
		track[id] = w;
		delta[id].ST = track[id].ST - track[id-1].ST;
		delta[id].ND = track[id].ND - track[id-1].ND;
	} else {
		id++;
		if(id > 0) {
			hidden[x]++;
			add[x]++;
			cout << "+ " << x << "\n";
		}
		int cnt = 0, cnt2 = 0;
		for(int i = 1; i <= n; ++i) {
			if(i!=1&&i!=n) cnt += hidden[i-1] * hidden[i] * hidden[i+1];
			cnt2 += hidden[i] * (hidden[i] - 1) * (hidden[i] - 2) / 6;
		}

		track[id].ST = cnt2;
		track[id].ND = cnt;
		if(id > 0) {
			delta[id].ST = track[id].ST - track[id-1].ST;
			delta[id].ND = track[id].ND - track[id-1].ND;
		}
		cout << cnt2 << " " << cnt << "\n";
	}

}

int main() {
	srand(time(NULL));
	if(debug) {
		n = rand(4,6);
		cout << "array : (";
		for(int i = 1; i <= n; ++i) {
			hidden[i] = rand(0,n);
			cout << hidden[i] << " ";
		}
		cout << ")\n";
	}
	else cin >> n;
	for(int i = 3; i <= n+4; ++i) {
		p[i] = i * (i-1) * (i-2) / 6;
		inv[p[i] - p[i-1]] = i - 1;
	}
	for(int i = 1; i <= n; ++i) ans[i] = -1;
	if(debug) {
		id = -1;
		query(1);
	}
	else cin >> track[0].ST >> track[0].ND;
	query(1);
	int trzy = -1;
	bool special = 0;
	if(delta[1].ST > 0) ans[1] = inv[delta[1].ST];
	if(ans[1] != -1) {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(3);
			ans[3] = delta[1].ND / ((ans[2]));
		} else {
			if(delta[2].ND == 0) {
				ans[3] = 0;
				query(2);
				if(delta[3].ST > 0) ans[2] = 1;
				else ans[2] = 0;
				query(3);
			} else {
				if(delta[1].ND > 0) {
					ans[2] = ans[3] = 1;
				} else {
					ans[3] = 1;
					ans[2] = 0;
				}
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
			}
		}
	} else {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(1);
			if(delta[3].ST > 0) ans[1] = 1;
			else ans[1] = 0;
			query(3);
			if(delta[4].ST > 0) ans[3] = inv[delta[4].ST];
			else {
				if(delta[1].ND == 0) ans[3] = 0;
				else ans[3] = 1;
			}
		} else {
			if(delta[1].ND > 0) {
				ans[2] = 1;
				query(1);
				if(delta[id].ST > 0) ans[1] = 1;
				else ans[1] = 0;
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				else ans[3] = 1;
			} else {
				if(delta[2].ND > 0) {
					ans[2] = 0;
					ans[3] = 1;
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					query(3);
					if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				} else {
					ans[3] = 0;
					query(3);
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					ans[2] = delta[id].ND - 1;
					add[1]--;
					special = 1;
				}
			}
		}
	}
	trzy = id - special;
	for(int i = 4; i < n; ++i) {
		ll ilo = delta[trzy].ND - (ans[i-2]+add[i-2])*(ans[i-3]+(add[i-3]));
		query(i);
		//cout << "(" << delta[id].ST << ")\n";
		if(delta[id].ST > 0) {
			ans[i] = inv[delta[id].ST];
		} else {
			if(ilo == 0) ans[i] = 0;
			else ans[i] = 1;
		}
		trzy = id;
	}
	if(n > 3) ans[n] = (delta[trzy].ND - (ans[n-2]+add[n-2])*(ans[n-3]+add[n-3]))/(ans[n-2]+add[n-2]);
	cout << "! ";
	for(int i = 1; i <= n; ++i) {
		cout << ans[i] << " ";
	}
	fflush(stdout);
}


#include <bits/stdc++.h>
#define PB push_back
#define ST first
#define ND second
#define _ ios_base::sync_with_stdio(0); cin.tie(0);
//mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

using namespace std;

using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;

const int nax = 110;
int n;
int ans[nax];
int add[nax];
pair<ll,ll>track[nax], delta[nax];
int inv[100*100*100],p[nax];
int id;

void query(int x) {
	cout << "+ " << x << "\n";
	add[x]++;
	fflush(stdout);
	pair<ll,ll>w;
	cin >> w.ST >> w.ND;
	id++;
	track[id] = w;
	delta[id].ST = track[id].ST - track[id-1].ST;
	delta[id].ND = track[id].ND - track[id-1].ND;
}

int main() {
	cin >> n;
	for(int i = 3; i <= n; ++i) {
		p[i] = i * (i-1) * (i-2) / 6;
		inv[p[i] - p[i-1]] = i - 1;
	}
	for(int i = 1; i <= n; ++i) ans[i] = -1;
	cin >> track[0].ST >> track[0].ND;
	query(1);
	int trzy = -1;
	bool special = 0;
	if(delta[1].ST > 0) ans[1] = inv[delta[1].ST];
	if(ans[1] != -1) {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(3);
			ans[3] = delta[1].ND / ((ans[1] + 1) * (ans[2]));
		} else {
			if(delta[2].ND == 0) {
				ans[3] = 0;
				query(2);
				if(delta[3].ST > 0) ans[2] = 1;
				else ans[2] = 0;
				query(3);
			} else {
				if(delta[1].ND > 0) {
					ans[2] = ans[3] = 1;
				} else {
					ans[3] = 1;
					ans[2] = 0;
				}
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
			}
		}
	} else {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(1);
			if(delta[3].ST > 0) ans[1] = 1;
			else ans[1] = 0;
			query(3);
			if(delta[4].ST > 0) ans[3] = inv[delta[4].ST];
			else {
				if(delta[1].ND == 0) ans[3] = 0;
				else ans[3] = 1;
			}
		} else {
			if(delta[1].ND > 0) {
				ans[2] = 1;
				query(1);
				if(delta[id].ST > 0) ans[1] = 1;
				else ans[1] = 0;
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				else ans[3] = 1;
			} else {
				if(delta[2].ND > 0) {
					ans[2] = 0;
					ans[3] = 1;
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					query(3);
					if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				} else {
					ans[3] = 0;
					query(3);
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					ans[2] = delta[id].ND - 1;
					add[1]--;
					special = 1;
				}
			}
		}
	}
	trzy = id - special;
	for(int i = 4; i < n; ++i) {
		ll ilo = delta[trzy].ND - (ans[i-2]+add[i-2])*(ans[i-3]+(add[i-3]));
		query(i);
		//cout << "(" << delta[id].ST << ")\n";
		if(delta[id].ST > 0) {
			ans[i] = inv[delta[id].ST];
		} else {
			if(ilo == 0) ans[i] = 0;
			else ans[i] = 1;
		}
		trzy = id;
	}
	if(n > 3) ans[n] = (delta[trzy].ND - (ans[n-2]+add[n-2])*(ans[n-3]+add[n-3]))/(ans[n-2]+add[n-2]);
	cout << "! ";
	for(int i = 1; i <= n; ++i) {
		cout << ans[i] << " ";
	}
	fflush(stdout);
}


#include <bits/stdc++.h>
#define PB push_back
#define ST first
#define ND second
#define _ ios_base::sync_with_stdio(0); cin.tie(0);
//mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

using namespace std;

using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;

const int nax = 110;
int n;
int ans[nax];
int add[nax];
pair<ll,ll>track[nax], delta[nax];
int inv[100*100*100],p[nax];
int id;

void query(int x) {
	cout << "+ " << x << "\n";
	add[x]++;
	fflush(stdout);
	pair<ll,ll>w;
	cin >> w.ST >> w.ND;
	id++;
	track[id] = w;
	delta[id].ST = track[id].ST - track[id-1].ST;
	delta[id].ND = track[id].ND - track[id-1].ND;
}

int main() {
	cin >> n;
	for(int i = 3; i <= n; ++i) {
		p[i] = i * (i-1) * (i-2) / 6;
		inv[p[i] - p[i-1]] = i - 1;
	}
	for(int i = 1; i <= n; ++i) ans[i] = -1;
	cin >> track[0].ST >> track[0].ND;
	query(1);
	if(delta[1].ST > 0) ans[1] = inv[delta[1].ST];
	if(ans[1] != -1) {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(3);
			ans[3] = delta[1].ND / ((ans[1] + 1) * (ans[2]));
		} else {
			if(delta[2].ND == 0) {
				ans[3] = 0;
				query(2);
				if(delta[3].ST > 0) ans[2] = 1;
				else ans[2] = 0;
				query(3);
			} else {
				if(delta[1].ND > 0) {
					ans[2] = ans[3] = 1;
				} else {
					ans[3] = 1;
					ans[2] = 0;
				}
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
			}
		}
	} else {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(1);
			if(delta[3].ST > 0) ans[1] = 1;
			else ans[1] = 0;
			query(3);
			if(delta[4].ST > 0) ans[3] = inv[delta[4].ST];
			else {
				if(delta[1].ND == 0) ans[3] = 0;
				else ans[3] = 1;
			}
		} else {
			if(delta[1].ND > 0) {
				ans[2] = 1;
				query(1);
				if(delta[id].ST > 0) ans[1] = 1;
				else ans[1] = 0;
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				else ans[3] = 1;
			} else {
				if(delta[2].ND > 0) {
					ans[2] = 0;
					ans[3] = 1;
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					query(3);
					if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				} else {
					ans[3] = 0;
					query(3);
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					ans[2] = delta[id].ND - 1;
					id--;
					add[1]--;
				}
			}
		}
	}
	for(int i = 4; i < n; ++i) {
		ll ilo = delta[id].ND - (ans[i-2]+add[i-2])*(ans[i-3]+(add[i-3]));
		query(i);
		if(delta[id].ST > 0) {
			ans[i] = inv[delta[id].ST];
		} else {
			if(ilo == 0) ans[i] = 0;
			else ans[i] = 1;
		}
	}
	if(n > 3) ans[n] = (delta[id].ND - (ans[n-2]+add[n-2])*(ans[n-3]+add[n-3]))/(ans[n-2]+add[n-2]);
	cout << "! ";
	for(int i = 1; i <= n; ++i) {
		cout << ans[i] << " ";
	}
	fflush(stdout);
}


#include <bits/stdc++.h>
#define PB push_back
#define ST first
#define ND second
#define _ ios_base::sync_with_stdio(0); cin.tie(0);
//mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

using namespace std;

using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;

const int nax = 110;
int n;
int ans[nax];
int add[nax];
pair<ll,ll>track[nax], delta[nax];
int inv[100*100*100],p[nax];
int id;

void query(int x) {
	cout << "+ " << x << "\n";
	add[x]++;
	fflush(stdout);
	pair<ll,ll>w;
	cin >> w.ST >> w.ND;
	id++;
	track[id] = w;
	delta[id].ST = track[id].ST - track[id-1].ST;
	delta[id].ND = track[id].ND - track[id-1].ND;
}

int main() {
	cin >> n;
	for(int i = 3; i <= n; ++i) {
		p[i] = i * (i-1) * (i-2) / 6;
		inv[p[i] - p[i-1]] = i - 1;
	}
	for(int i = 1; i <= n; ++i) ans[i] = -1;
	cin >> track[0].ST >> track[0].ND;
	query(1);
	if(delta[1].ST > 0) ans[1] = inv[delta[1].ST];
	if(ans[1] != -1) {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(3);
			ans[3] = delta[1].ND / ((ans[1] + 1) * (ans[2]));
		} else {
			if(delta[2].ND == 0) {
				ans[3] = 0;
				query(2);
				if(delta[3].ST > 0) ans[2] = 1;
				else ans[2] = 0;
				query(3);
			} else {
				if(delta[1].ND > 0) {
					ans[2] = ans[3] = 1;
				} else {
					ans[3] = 1;
					ans[2] = 0;
				}
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
			}
		}
	} else {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(1);
			if(delta[3].ST > 0) ans[1] = 1;
			else ans[1] = 0;
			query(3);
			if(delta[4].ST > 0) ans[3] = inv[delta[4].ST];
			else {
				if(delta[1].ND == 0) ans[3] = 0;
				else ans[3] = 1;
			}
		} else {
			if(delta[1].ND > 0) {
				ans[2] = 1;
				query(1);
				if(delta[id].ST > 0) ans[1] = 1;
				else ans[1] = 0;
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				else ans[3] = 1;
			} else {
				if(delta[2].ND > 0) {
					ans[2] = 0;
					ans[3] = 1;
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					query(3);
				} else {
					ans[3] = 0;
					query(3);
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					ans[2] = delta[id].ND - 1;
					id--;
					add[1]--;
				}
			}
		}
	}
	for(int i = 4; i < n; ++i) {
		ll ilo = delta[id].ND - (ans[i-2]+add[i-2])*(ans[i-3]+(add[i-3]));
		query(i);
		if(delta[id].ST > 0) {
			ans[i] = inv[delta[id].ST];
		} else {
			if(ilo == 0) ans[i] = 0;
			else ans[i] = 1;
		}
	}
	if(n > 3) ans[n] = (delta[id].ND - (ans[n-2]+add[n-2])*(ans[n-3]+add[n-3]))/(ans[n-2]+add[n-2]);
	cout << "! ";
	for(int i = 1; i <= n; ++i) {
		cout << ans[i] << " ";
	}
	fflush(stdout);
}


#include <bits/stdc++.h>
#define PB push_back
#define ST first
#define ND second
#define _ ios_base::sync_with_stdio(0); cin.tie(0);
//mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

using namespace std;

using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;

const int nax = 110;
int n;
int ans[nax];
int add[nax];
pair<ll,ll>track[nax], delta[nax];
int inv[100*100*100],p[nax];
int id;

void query(int x) {
	cout << "+ " << x << "\n";
	add[x]++;
	fflush(stdout);
	pair<ll,ll>w;
	cin >> w.ST >> w.ND;
	id++;
	track[id] = w;
	delta[id].ST = track[id].ST - track[id-1].ST;
	delta[id].ND = track[id].ND - track[id-1].ND;
}

int main() {
	cin >> n;
	for(int i = 3; i <= n; ++i) {
		p[i] = i * (i-1) * (i-2) / 6;
		inv[p[i] - p[i-1]] = i - 1;
	}
	for(int i = 1; i <= n; ++i) ans[i] = -1;
	cin >> track[0].ST >> track[0].ND;
	query(1);
	int trzy = -1;
	bool special = 0;
	if(delta[1].ST > 0) ans[1] = inv[delta[1].ST];
	if(ans[1] != -1) {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(3);
			ans[3] = delta[1].ND / ((ans[1] + 1) * (ans[2]));
		} else {
			if(delta[2].ND == 0) {
				ans[3] = 0;
				query(2);
				if(delta[3].ST > 0) ans[2] = 1;
				else ans[2] = 0;
				query(3);
			} else {
				if(delta[1].ND > 0) {
					ans[2] = ans[3] = 1;
				} else {
					ans[3] = 1;
					ans[2] = 0;
				}
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
			}
		}
	} else {
		query(2);
		if(delta[2].ST > 0) {
			ans[2] = inv[delta[2].ST];
			query(1);
			if(delta[3].ST > 0) ans[1] = 1;
			else ans[1] = 0;
			query(3);
			if(delta[4].ST > 0) ans[3] = inv[delta[4].ST];
			else {
				if(delta[1].ND == 0) ans[3] = 0;
				else ans[3] = 1;
			}
		} else {
			if(delta[1].ND > 0) {
				ans[2] = 1;
				query(1);
				if(delta[id].ST > 0) ans[1] = 1;
				else ans[1] = 0;
				query(3);
				if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				else ans[3] = 1;
			} else {
				if(delta[2].ND > 0) {
					ans[2] = 0;
					ans[3] = 1;
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					query(3);
					if(delta[id].ST > 0) ans[3] = inv[delta[id].ST];
				} else {
					ans[3] = 0;
					query(3);
					query(1);
					if(delta[id].ST > 0) ans[1] = 1;
					else ans[1] = 0;
					ans[2] = delta[id].ND - 1;
					add[1]--;
					special = 1;
				}
			}
		}
	}
	trzy = id - special;
	for(int i = 4; i < n; ++i) {
		ll ilo = delta[trzy].ND - (ans[i-2]+add[i-2])*(ans[i-3]+(add[i-3]));
		query(i);
		//cout << "(" << delta[id].ST << ")\n";
		if(delta[id].ST > 0) {
			ans[i] = inv[delta[id].ST];
		} else {
			if(ilo == 0) ans[i] = 0;
			else ans[i] = 1;
		}
		trzy = id;
	}
	if(n > 3) ans[n] = (delta[id].ND - (ans[n-2]+add[n-2])*(ans[n-3]+add[n-3]))/(ans[n-2]+add[n-2]);
	cout << "! ";
	for(int i = 1; i <= n; ++i) {
		cout << ans[i] << " ";
	}
	fflush(stdout);
}


#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()

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

int main()
{

#ifndef ONLINE_JUDGE
    //freopen("input.txt", "r", stdin);
#endif

    int n;
    scanf("%d", &n);
    vector<int> ans(n + 1, -1), c(n + 1);

    int E, S, prevE, prevS;
    scanf("%d %d", &E, &S);

    auto ask = [&](int x) {
        printf("+ %d\n", x);
        fflush(stdout);
        prevE = E;
        prevS = S;
        scanf("%d %d", &E, &S);
    };
    auto dE = [&]() {
        return E - prevE;
    };
    auto dS = [&]() {
        return S - prevS;
    };

    auto revC = [&](int Cn2) {
        int x = 1;
        while(x * (x - 1) / 2 != Cn2) ++x;
        return x;
    };

    ask(1);
    int ab = dS();
    ask(3);
    ask(1);
    ans[2] = dS() - ab;
    c[2] = ans[2];
    ans[1] = revC(dE()) - 1;
    c[1] = ans[1] + 2;

    for (int i = 3; i < n; ++i) {
        ask(i);
        if (ans[i] == -1)
            ans[i] = revC(dE());
        if (dS() - c[i - 2] * c[i - 1] == 0)
            ans[i + 1] = 0;

        c[i] = ans[i] + 1;
    }
    ans[3]--;

    /*
    for (int i = 1; i < n; ++i)
        printf("%d ", c[i]);
    printf("\n");
    */

    if (ans[n] == -1) {
        int curS = 0;
        for (int i = 2; i < n; ++i)
            curS += c[i - 2] * c[i - 1] * c[i];
        ans[n] = (S - curS) / (c[n - 2] * c[n - 1]);
    }

    printf("! ");
    for (int i = 1; i <= n; ++i)
        printf("%d ", ans[i]);

}