#include <bits/stdc++.h>
using namespace std;
#define int long long
#define moduro (int)(1e9 + 7)

int MOD(int a){
	return (a %= moduro) >= 0 ? a : a + moduro;
}

int power(int a, int N){
	if(N == 0){
		return 1;
	}
	else if(N % 2 == 0){
		return power(MOD(a * a), N / 2);
	}
	else{
		return MOD(a* power(a, N - 1));
	}
}

int inverse(int a){
	return power(a, moduro - 2);
}

struct Func{
	vector<int> a;
	vector<int> b;
	int c;

	Func(int L) : a(L + 1, 0), b(L + 1, 0), c(0){}
};

int L;

Func integral(Func f, char x){
	int i;
	Func ans(L);
	if(x == '<'){
		for(i = 0; i < L; i++){
			ans.a[i + 1] = MOD(f.a[i] * inverse(i + 1));
			ans.b[i + 1] = MOD(f.b[i] * inverse(i + 1));
		}
		ans.c = MOD(-f.c);
		ans.a[0] = MOD(f.c);
	}
	else{
		ans.b[0] = MOD(-f.c);
		for(i = 0; i < L; i++){
			ans.a[i + 1] = MOD(-f.a[i] * inverse(i + 1));
			ans.b[i + 1] = MOD(-f.b[i] * inverse(i + 1));
			ans.a[0] = MOD(ans.a[0] + f.a[i] * inverse(i + 1));
			ans.b[0] = MOD(ans.b[0] + f.b[i] * inverse(i + 1));
		}
		ans.c = MOD(f.c);
	}
	return ans;
}

Func Func_plus(Func f1, Func f2){
	Func ans(L);
	for(int i = 0; i <= L; i++){
		ans.a[i] = MOD(f1.a[i] + f2.a[i]);
		ans.b[i] = MOD(f1.b[i] + f2.b[i]);
	}
	ans.c = MOD(f1.c + f2.c);
	return ans;
}

tuple<int, int, int> solve(vector<int> &interval){
	int i, j;
	L = interval.size();
	for(i = 0; i < interval.size(); i++){
		if(!(interval[i] == 1 || interval[i] == 2)){
			return make_tuple(0, 0, 0);
		}
		L += interval[i];
	}
	Func f(L);
	f.c = 1;
	for(i = 0; i < interval.size(); i++){
		if(interval[i] == 1){
			Func f1 = integral(f, '<');
			Func f2 = integral(f, '>');
			Func f11 = integral(f1, '<');
			Func f12 = integral(f1, '>');
			Func f22 = integral(f2, '>');
			f = Func_plus(Func_plus(f11, f12), f22);
		}
		else{
			Func f1 = integral(f, '<');
			Func f11 = integral(f1, '<');
			Func f12 = integral(f1, '>');
			Func f112 = integral(f11, '>');
			Func f122 = integral(f12, '>');
			f = Func_plus(f112, f122);
		}
	}
	int p = 0, q = 0, r = 0;
	//ここから部分積分
	p = MOD(f.c * inverse(2));
	r = MOD(-f.c * inverse(2));
	vector<vector<int>> as(L + 2, vector<int>(L + 1, 0));
	for(i = 0; i <= L; i++){
		as[0][i] = f.a[i];
	}
	for(i = 0; i <= L; i++){
		p = MOD(p + as[i][0]);
		for(j = 0; j <= L; j++){
			q = MOD(q - as[i][j]);
		}
		for(j = 1; j <= L; j++){
			as[i + 1][j - 1] = MOD(j * as[i][j]);
		}
	}
	vector<vector<int>> bs(L + 2, vector<int>(L + 1, 0));
	for(i = 0; i <= L; i++){
		bs[0][i] = f.b[i];
	}
	for(i = 0; i <= L; i++){
		q = MOD(q + bs[i][0]);
		for(j = 0; j <= L; j++){
			r = MOD(r - bs[i][j]);
		}
		for(j = 1; j <= L; j++){
			bs[i + 1][j - 1] = MOD(j * bs[i][j]);
		}
	}
	return make_tuple(p, q, r);
}

string edge_begin[3] = {"X", "X-", "X--"};
string edge_end[3] = {"X", "-X", "--X"};

signed main(){
	int N, i, j, k;
	int p = 0, q = 0, r = 0;
	scanf("%lld", &N);
	string s;
	cin >> s;
	for(i = 0; i < 3; i++){
		for(j = 0; j < 3; j++){
			string s_sub = edge_begin[i] + s + edge_end[j];
			int rast = 0;
			vector<int> interval(0);
			for(k = 1; k < s_sub.size(); k++){
				if(s_sub[k] == 'X'){
					interval.push_back(k - rast - 1);
					rast = k;
				}
			}
			tuple<int, int, int> res = solve(interval);
			p = MOD(p + get<0>(res));
			q = MOD(q + get<1>(res));
			r = MOD(r + get<2>(res));
		}
	}
	printf("%lld %lld %lld\n", p, q, r);
	return 0;
}

Measured memory_bytes: 16196