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

typedef pair<int,int> pii;
typedef pair<string,int> psi;
typedef pair<int,string> pis;
typedef array<int,2> aii;
typedef array<int,3> aiii;
typedef array<int,4> aiiii;
typedef unsigned long long ull;
typedef long long int ll;
typedef array<ll,2> all;
typedef array<ll,3> alll;

#define pb push_back
#define ff first
#define ss second
#define MAX 1000005
#define MOD 1000000007
#define INF 1e9+100
vector<int>adj[MAX];
int xMove[] = { 0,1,0,-1,1,1,-1,-1, 2, 2, -2, -2, 1, 1, -1, -1 };
int yMove[] = { 1,0,-1,0,1,-1,1,-1, 1, -1, 1, -1, 2, -2, 2, -2 };
string arr[65];
ll dp[65][2],n;
ll solve(int i, int p)
{
    if(i==n)
        return p==1;
    if(dp[i][p]!=-1)
        return dp[i][p];
    ll ans=0;
    ans+=solve(i+1,arr[i]=="AND"?p&1:p|1);
    ans+=solve(i+1,arr[i]=="AND"?p&0:p|0);
    return dp[i][p]=ans;
}
int main()
{
    //freopen("joseph.in","r",stdin);
    //freopen("output.txt","w",stdout);
    cin.tie(0),cout.tie(0);
    ios_base::sync_with_stdio(0);
    cout.setf(ios::fixed);
    cout.precision(10);
    int TC=1;
    int m,k,q;

    //cin>>TC;
    for(int t1=1; t1<=TC; t1++)
    {
        cin>>n;
        for(int i=0; i<n; i++)
            cin>>arr[i];
        memset(dp,-1,sizeof dp);
        cout<<solve(0,1)+solve(0,0)<<endl;
    }
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define repd(i,a,b) for (int i=(a);i<(b);i++)
#define rep(i,n) repd(i,0,n)
#define all(x) (x).begin(),(x).end()
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
typedef long long ll;
typedef pair<int, int> P;
typedef vector<int> vec;
using Graph = vector<vector<int>>;
const long long INF = 1LL<<60;
const int MOD = 1000000007;

struct SegmentTree {
private:
    int n;
    vector<int> node;

public:
    // 元配列 v をセグメント木で表現する
    SegmentTree(vector<int> v) {
        // 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
        // セグメント木全体で必要なノード数は 2n-1 個である
        int sz = v.size();
        n = 1; while (n < sz) n *= 2;
        node.resize(2 * n - 1, -MOD);

        // 最下段に値を入れたあとに、下の段から順番に値を入れる
        // 値を入れるには、自分の子の 2 値を参照すれば良い
        for (int i = 0; i < sz; i++) node[i + n - 1] = v[i];
        for (int i = n - 2; i >= 0; i--) node[i] = max(node[2 * i + 1], node[2 * i + 2]);
    }

    void update(int x, int val) {
        // 最下段のノードにアクセスする
        x += (n - 1);

        // 最下段のノードを更新したら、あとは親に上って更新していく
        node[x] = val;
        while (x > 0) {
            x = (x - 1) / 2;
            node[x] = max(node[2 * x + 1], node[2 * x + 2]);
        }
    }

    // 要求区間 [a, b) 中の要素の最小値を答える
// k := 自分がいるノードのインデックス
// 対象区間は [l, r) にあたる

    int getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
        // 最初に呼び出されたときの対象区間は [0, n)
        if (r < 0) r = n;

        // 要求区間と対象区間が交わらない -> 適当に返す
        if (r <= a || b <= l) return -MOD;

        // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
        if (a <= l && r <= b) return node[k];

        // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
        // 左側の子を vl ・ 右側の子を vr としている
        // 新しい対象区間は、現在の対象区間を半分に割ったもの
        int vl = getmin(a, b, 2 * k + 1, l, (l + r) / 2);
        int vr = getmin(a, b, 2 * k + 2, (l + r) / 2, r);
        return max(vl, vr);
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n;cin>>n;
    vec a(n);
    rep(i,n){
        string s;
        cin>>s;
        if(s=="AND")a[i]=0;
        else a[i]=1;
    }
    vector<vector<ll>> dp(n+1,vector<ll>(2));
    dp[0][0]=1;dp[0][1]=1;
    rep(i,n){
        if(a[i]==0){
            dp[i+1][1]=dp[i][1];
            dp[i+1][0]=dp[i][1]+2*dp[i][0];
        }
        else{
            dp[i+1][1]=dp[i][0]+dp[i][1]*2;
            dp[i+1][0]=dp[i][0];
        }
    }
    cout<<dp[n][1]<<endl;
    return 0;
}