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

//template
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(a);i>(b);i--)
#define ALL(v) (v).begin(),(v).end()
typedef long long int ll; typedef pair<ll, ll> P;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<typename A,size_t N,typename T>void Fill(A(&array)[N],const T &val){fill((T*)array, (T*)(array+N), val);}
const int inf = 0x3fffffff; const ll INF = 0x3fffffffffffffff;
//template end

ll mod=1e9+7;
struct Mint {
    ll val;
    Mint inv() const{
        ll tmp,a=val,b=mod,x=1,y=0;
        while(b)tmp=a/b,a-=tmp*b,swap(a,b),x-=tmp*y,swap(x,y);
        return Mint(x);
    }
public:
    Mint():val(0){}
    Mint(ll x):val(x>=0?x%mod:x%mod+mod){}
    int mtoi(){return this->val; }
    Mint pow(ll t){Mint res=1,b=*this; while(t){if(t&1)res*=b;b*=b;t>>=1;}return res;}
    Mint& operator+=(const Mint& x){if((val+=x.val)>=mod)val-=mod;return *this;}
    Mint& operator-=(const Mint& x){if((val+=mod-x.val)>=mod)val-=mod; return *this;}
    Mint& operator*=(const Mint& x){val=(ll)val*x.val%mod; return *this;}
    Mint& operator/=(const Mint& x){return *this *= x.inv();}
    bool operator==(const Mint& x) const{return val == x.val;}
    bool operator!=(const Mint& x) const{return val != x.val;}
    bool operator<(const Mint& x) const{return val < x.val;}
    bool operator<=(const Mint& x) const{return val <= x.val;}
    bool operator>(const Mint& x) const{return val > x.val;}
    bool operator>=(const Mint& x) const{return val >= x.val;}
    Mint operator+(const Mint& x) const{return Mint(*this)+=x;}
    Mint operator-(const Mint& x) const{return Mint(*this)-=x;}
    Mint operator*(const Mint& x) const{return Mint(*this)*=x;}
    Mint operator/(const Mint& x) const{return Mint(*this)/=x;}
};
struct factorial {
    vector<Mint> Fact, Finv;
public:
    factorial(int maxx){
        Fact.resize(maxx+1),Finv.resize(maxx+1); Fact[0]=Mint(1); rep(i,0,maxx)Fact[i+1]=Fact[i]*Mint(i+1);
        Finv[maxx]=Mint(1)/Fact[maxx]; rrep(i,maxx,0)Finv[i-1]=Finv[i]*Mint(i);
    }
    Mint fact(int n,bool inv=0){if(inv)return Finv[n];else return Fact[n];}
    Mint nPr(int n,int r){if(n<0||n<r||r<0)return Mint(0);else return Fact[n]*Finv[n-r];}
    Mint nCr(int n,int r){if(n<0||n<r||r<0)return Mint(0);else return Fact[n]*Finv[r]*Finv[n-r];}
};

typedef tuple<vector<Mint>,vector<Mint>,Mint> func;
typedef tuple<Mint,Mint,Mint> T;
func to_f(T t){return func{{get<0>(t)},{get<1>(t)},get<2>(t)};}
void v_add(vector<Mint> &a,vector<Mint> b){
    a.resize(max(a.size(),b.size()));
    rep(i,0,b.size())a[i]+=b[i];
}
void v_dec(vector<Mint> &a,vector<Mint> b){
    a.resize(max(a.size(),b.size()));
    rep(i,0,b.size())a[i]-=b[i];
}
void t_add(T &a,T b){get<0>(a)+=get<0>(b),get<1>(a)+=get<1>(b),get<2>(a)+=get<2>(b);}
void t_dec(T &a,T b){get<0>(a)-=get<0>(b),get<1>(a)-=get<1>(b),get<2>(a)-=get<2>(b);}
void f_add(func &a,func b){v_add(get<0>(a),get<0>(b)),v_add(get<1>(a),get<1>(b)),get<2>(a)+=get<2>(b);}
func f_dec(func a,func b){v_dec(get<0>(a),get<0>(b)),v_dec(get<1>(a),get<1>(b)),get<2>(a)-=get<2>(b); return a;}
void integral(func &f){
    vector<Mint> p=get<0>(f),q=get<1>(f);
    if(p.back()!=Mint(0))p.resize(p.size()+1); 
    if(q.back()!=Mint(0))q.resize(q.size()+1);
    rrep(i,p.size()-1,0)p[i]=p[i-1]/Mint(i); p[0]=0;
    rrep(i,q.size()-1,0)q[i]=q[i-1]/Mint(i); q[0]=0;
    get<0>(f)=p; get<1>(f)=q; get<2>(f)*=-1;
}
func int_x(func f){integral(f); return func(f_dec(f,func{{get<2>(f)},{0},0}));}
T int_1(func f){
    integral(f); T res;
    vector<Mint> p=get<0>(f),q=get<1>(f);
    rep(i,0,p.size())get<0>(res)+=p[i];
    rep(i,0,q.size())get<1>(res)+=q[i];
    get<0>(res)-=get<2>(f); get<1>(res)+=get<2>(f); return res;
}
Mint pre[1010][2];
void calc(){
    pre[0][0]=1; pre[0][1]=-1;
    rep(i,0,1005){
        pre[i+1][0]=pre[i][0]*Mint(i+1);
        pre[i+1][1]=pre[i][1]*Mint(i+1)-1;
    }
}
T int_e(func f){
    T res; vector<Mint> p=get<0>(f),q=get<1>(f);
    rep(i,0,p.size())get<0>(res)+=p[i]*pre[i][0],get<1>(res)+=p[i]*pre[i][1];
    rep(i,0,q.size())get<1>(res)+=q[i]*pre[i][0],get<2>(res)+=q[i]*pre[i][1];
    get<0>(res)+=get<2>(f)/2; get<2>(res)-=get<2>(f)/2; return res;
}

func dp[1010][2][3];

int main(){
    int n; scanf("%d",&n);
    string s; cin>>s; calc(); Fill(dp,func{{0},{0},0});
    if(s[0]=='X')dp[0][0][0]=func{{0},{0},1};
    else dp[0][0][1]=func{{0},{0},1},dp[0][1][2]=func{{1},{0},-1};
    rep(i,1,n){
        if(s[i]=='X'){
            f_add(dp[i][0][0],int_x(dp[i-1][1][0]));
            f_add(dp[i][0][0],int_x(dp[i-1][1][2]));
            f_add(dp[i][0][0],f_dec(to_f(int_1(dp[i-1][0][1])),int_x(dp[i-1][0][1])));
            f_add(dp[i][0][0],f_dec(to_f(int_1(dp[i-1][0][2])),int_x(dp[i-1][0][2])));
            f_add(dp[i][0][0],f_dec(to_f(int_1(dp[i-1][1][1])),int_x(dp[i-1][1][1])));
            f_add(dp[i][0][0],f_dec(to_f(int_1(dp[i-1][1][2])),int_x(dp[i-1][1][2])));
        }
        else{
            f_add(dp[i][0][1],int_x(dp[i-1][1][0]));
            f_add(dp[i][0][1],int_x(dp[i-1][1][2]));
            f_add(dp[i][1][2],int_x(dp[i-1][0][0]));
            f_add(dp[i][1][2],int_x(dp[i-1][0][2]));
            f_add(dp[i][0][1],f_dec(to_f(int_1(dp[i-1][0][0])),int_x(dp[i-1][0][0])));
            f_add(dp[i][0][1],f_dec(to_f(int_1(dp[i-1][0][2])),int_x(dp[i-1][0][2])));
            f_add(dp[i][0][1],f_dec(to_f(int_1(dp[i-1][1][0])),int_x(dp[i-1][1][0])));
            f_add(dp[i][0][1],f_dec(to_f(int_1(dp[i-1][1][2])),int_x(dp[i-1][1][2])));
        }
    } T ans;
    rep(i,0,2){
        t_add(ans,int_e(dp[n-1][i][0]));
        t_add(ans,int_1(dp[n-1][i][1]));
        t_dec(ans,int_e(dp[n-1][i][1]));
        t_add(ans,int_1(dp[n-1][i][2]));
    }
    printf("%d %d %d\n",get<0>(ans).mtoi(),get<1>(ans).mtoi(),get<2>(ans).mtoi());
    return 0;
}

Measured memory_bytes: 8832