//by yjz
#include<bits/stdc++.h>
using namespace std;
#define FF first
#define SS second
#define PB push_back
#define MP make_pair
#define foreach(it,s) for(__typeof((s).begin()) it=(s).begin();it!=(s).end();it++)
#ifndef LOCAL
#define cerr if(0)cout
#endif
typedef long long ll;
const int mod = 1e9+7;
ll qpow(ll x, ll k) {return k==0? 1: 1ll*qpow(1ll*x*x%mod,k>>1)*(k&1?x:1)%mod;}
const int maxn = 1011;
ll inv[maxn];
typedef pair<int,int> num;
typedef vector<pair<int,int> > poly;
num add(const num &x, const num &y)
{
	return MP((x.FF+y.FF)%mod, (x.SS+y.SS)%mod);
}
num sub(const num &x, const num &y)
{
	return MP((x.FF-y.FF)%mod, (x.SS-y.SS)%mod);
}
poly add(const poly &x, const poly &y)
{
	poly ret;
	ret.resize(max(x.size(), y.size()));
	for (int i=0; i<x.size(); i++) ret[i] = x[i];
	for (int i=0; i<y.size(); i++) ret[i] = add(ret[i], y[i]);
	return ret;
}
poly sub(const poly &x, const poly &y)
{
	poly ret;
	ret.resize(max(x.size(), y.size()));
	for (int i=0; i<x.size(); i++) ret[i] = x[i];
	for (int i=0; i<y.size(); i++) ret[i] = sub(ret[i], y[i]);
	return ret;
}
struct func
{
	//f(x) = a e^(-x)+ P(x)
	int a;
	poly v;
	func operator + (const func &t) const
	{
		func ret;
		ret.a = (a+t.a)%mod;
		ret.v = add(v, t.v);
		return ret;
	}
	func itg () const
	{
		func ret;
		ret.a = -a;
		ret.v.resize(v.size()+1);
		for (int i=0; i<v.size(); i++)
		{
			ret.v[i+1] = MP(1ll*v[i].FF*inv[i+1]%mod, 1ll*v[i].SS*inv[i+1]%mod);
		}
		return ret;
	}
	
	pair<int,int> get0() const
	{
		pair<int,int> ret = MP(a, 0);
		if (v.size()>0) ret = add(ret, v[0]);
		return ret;
	}
	pair<int,int> get1() const
	{
		pair<int,int> ret = MP(0, a);
		for (auto x : v) ret = add(ret, x);
		return ret;
	}
	func trans0() const
	{
		func ret = itg();
		ret.v = sub(ret.v, poly{ret.get0()});
		return ret;
	}
	func trans1() const
	
	{
		func ret = itg();
		ret.v = sub(poly{ret.get1()}, ret.v);
		ret.a = -ret.a;
		return ret;
	}
	void debug()
	{
		cerr<<"func:"<<endl;
		cerr<<a<<" e^(-x) + ";
		for (auto t : v) cerr<<t.FF<<","<<t.SS<<" "; cerr<<endl;
	}
};
/*
前i位已经填完 第i个随机数是x 0/1表示第i位之前的极长下降序列奇偶性 0/1表示第i位之后的极长下降序列的奇偶性 
f[i][0/1][0/1](x) = a*e^(-x)+P(x)
*/
func dp[maxn][2][2];
int n;
char s[maxn];
void upd(func &x, func v)
{
	x = x+v;
}
void calc_itg(int C, int coef0, int coef1, ll &a, ll &b, ll &c)
{
	b = (b-coef0)%mod;
	c = (c-coef1)%mod;
	if (C==0)
	{
		a = (a+coef0)%mod;
		b = (b+coef1)%mod;
	}
	else calc_itg(C-1, 1ll*C*coef0%mod, 1ll*C*coef1%mod, a, b, c);
}
int main()
{
	for (int i=1; i<maxn; i++) inv[i] = qpow(i, mod-2);
	cin>>n;
	scanf("%s", s+1);
	if (s[1]=='X')
	{
		dp[1][0][0].a = 1;
	}
	else
	{
		dp[1][0][1].a = 1;
		dp[1][1][0].a = dp[1][1][1].a = mod-1;
		dp[1][1][0].v = dp[1][1][1].v = {MP(1, 0)};
	}
	for (int i=1; i<n; i++)
	{
		for (int t0=0; t0<2; t0++)
		{
			for (int t1=0; t1<2; t1++)
			{
				if ((s[i]=='X')^(t0==0&&t1==0)) continue;
				// <
				if (t1==0)
				{
					upd(dp[i+1][t0^1][0], dp[i][t0][t1].trans0());
					upd(dp[i+1][t0^1][1], dp[i][t0][t1].trans0());
				}
				// >
				upd(dp[i+1][0][t1^1], dp[i][t0][t1].trans1());
				
			}
		}
	}
	ll ansa=0, ansb=0, ansc=0;
	for (int t0=0; t0<2; t0++)
	{
		for (int t1=0; t1<2; t1++)
		{
			if ((s[n]=='X')^(t0==0&&t1==0)) continue;
//			cerr<<"t0="<<t0<<" t1="<<t1<<endl;
			func &cur = dp[n][t0][t1];
//			cur.debug();
			ll a=0, b=0, c=0;
			c = -1ll*cur.a*inv[2]%mod;
			a = (a+1ll*cur.a*inv[2])%mod;
			for (int i=0; i<cur.v.size(); i++) calc_itg(i, cur.v[i].FF, cur.v[i].SS, a, b, c);
			if (t1==1)
			{
				a = -a;
				b = -b;
				c = -c;
				pair<int,int> p = sub(cur.itg().get1(), cur.itg().get0());
				a = (a+p.FF)%mod;
				b = (b+p.SS)%mod;
			}
//			cerr<<a<<" "<<b<<" "<<c<<endl;
			ansa = (ansa+a)%mod;
			ansb = (ansb+b)%mod;
			ansc = (ansc+c)%mod;
		}
	}
	cout<<(ansa+mod)%mod<<" "<<(ansb+mod)%mod<<" "<<(ansc+mod)%mod<<endl;
	return 0;
}


Measured memory_bytes: 10368