Problem:
問題名 箱根駅伝
日本のお正月の風物詩に箱根駅伝があります。箱根駅伝は、各チーム 10 人の走者が中継所ごとに襷をつなぎながらゴールを目指すというものです。テレビの放送では中継所で各チームの通過順位と共に前の中継所からの順位変動が表示されます。そこで、それを見て前の中継所の各チームの通過順として考えられるものが何通りあるか答えてください。ありえた通過順の数は非常に大きくなりうるので、1,000,000,007 で割った余りで答えて下さい。
Input
入力は以下の形で与えられます
n
c
1
c
2
...
c
n
1行目にはチーム数を表す数字
n
(
1 ≤ n ≤ 200
) が、続く
n
行には 1 位から順に前の中継所からの順位変動
c
i
('
D
' なら順位が落ちてる、'
U
' なら順位が上がってる、'
-
' なら順位が変わってない) が書いてあります。
Output
前の中継所でありえた通過順が何通りかを、 1,000,000,007 で割ったあまりで 1 行で出力して下さい。
Sample Input 1
3
-
U
D
Output for the Sample Input 1
1
この中継所を 1 位、 2 位、 3 位で通過したチームのチーム名をそれぞれ A, B, C とすると、前の中継所の通過順として考えられるのは 1 位：チーム A, 2 位：チーム C, 3 位：チーム B の 1 通りのみです。
Sample Input 2
5
U
U
-
D
D
Output for the Sample Input 2
5
この中継所の通過順にチーム名を A, B, C, D, E とすると、前の中継所の通過順として考えられるのは {D, E, C, A, B}, {D, E, C, B, A}, {E, D, C, A, B}, {E, D, C, B, A}, {D, A, C, E, B} の5通りです。
Sample Input 3
8
U
D
D
D
D
D
D
D
Output for the Sample Input 3
1
Sample Input 4
10
U
D
U
D
U
D
U
D
U
D
Output for the Sample Input 4
608
Sample Input 5
2
D
U
Output for the Sample Input 5
0

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)

using ll = long long;
const ll mod = 1000000007;

ll mul(ll a, ll b) {
    return (a * b) % mod;
}
void add(ll &a, ll b) {
    a += b;
    if(a >= mod) a -= mod;
}
int main() {
    int n; cin >> n;
    vector<int> v;
    rep(i, n) {
        string s; cin >> s;
        if(s == "-") continue;
        v.pb(s == "U");
    }
    n = v.size();
    if(n == 0) {
        cout << 1 << endl;
        return 0;
    }
    vector dp(n + 1, vector(n + 1, 0LL));
    dp[0][0] = 1;
    foa(e, v) {
        vector nx(n + 1, vector(n + 1, 0LL));
        if(e) { // U
            rep(i, n + 1) rep(j, n + 1) {
                if(i < n and j < n) add(nx[i + 1][j + 1], dp[i][j]);
                add(nx[i][j], mul(dp[i][j], j));
            }
        } else {
            rep(i, n + 1) rep(j, n + 1) {
                if(i and j) add(nx[i - 1][j - 1], mul(dp[i][j], mul(i, j)));
                add(nx[i][j], mul(dp[i][j], i));
            }
        }
        dp = move(nx);
    }
    cout << dp[0][0] << endl;
    
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 4096
final_rank: 4

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

using ll = long long;

const ll MOD = 1e9 + 7;

int main() {
  ll N; cin >> N;
  vector<ll> C(N, 0);
  for (int i = 0; i < N; ++i) {
    char c; cin >> c;
    if (c == 'U') C[i] = 1;
    if (c == 'D') C[i] = -1;
    if (c == '-') C[i] = 0;
  }
  
  vector dp(N+1, vector<ll>(N+1, 0));
  vector ndp = dp;
  
  dp[0][0] = 1;
  for (int i = 0; i < N; ++i) {
    for (int l = 0; l <= N; ++l) {
      for (int r = 0; r <= N; ++r) {
        vector< array<ll, 3> > diffs;
        if (C[i] == 0) {
          diffs.push_back({0, 0, 1});
        }
        if (C[i] == -1) {
          diffs.push_back({0, 0, l});
          diffs.push_back({-1, -1, l * r});
        }
        if (C[i] == 1) {
          diffs.push_back({0, 0, r});
          diffs.push_back({1, 1, 1});
        }
        
        for (auto [dl, dr, w] : diffs) {
          ll nl = l + dl, nr = r + dr;
          if (!(0 <= nl && nl <= N)) continue;
          if (!(0 <= nr && nr <= N)) continue;
          ndp[nl][nr] += dp[l][r] * w;
          ndp[nl][nr] %= MOD;
          
          // cout << i << " " << nl << " " << nr << " " << ndp[nl][nr] << endl;
        }
      }
    }
    
    swap(dp, ndp);
    ndp.assign(N+1, vector<ll>(N+1, 0));
  }
  
  ll res = dp[0][0];
  cout << res << endl;
  
  return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 4224
final_rank: 16

code_snippet: //include
//------------------------------------------
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
#include <limits>
#include <unordered_map>
#include <random>


using namespace std;

typedef long long LL;

const int INF = (int)1000000007;
const LL MOD = (LL)1000000007;//10^9+7
const LL INF2 = (LL)100000000000000000;//10^18

template<int MOD> struct Fp {
	long long val;
	constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
		if (val < 0) val += MOD;
	}
	constexpr int getmod() { return MOD; }
	constexpr Fp operator - () const noexcept {
		return val ? MOD - val : 0;
	}
	constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
	constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
	constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
	constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
	constexpr Fp& operator += (const Fp& r) noexcept {
		val += r.val;
		if (val >= MOD) val -= MOD;
		return *this;
	}
	constexpr Fp& operator -= (const Fp& r) noexcept {
		val -= r.val;
		if (val < 0) val += MOD;
		return *this;
	}
	constexpr Fp& operator *= (const Fp& r) noexcept {
		val = val * r.val % MOD;
		return *this;
	}
	constexpr Fp& operator /= (const Fp& r) noexcept {
		long long a = r.val, b = MOD, u = 1, v = 0;
		while (b) {
			long long t = a / b;
			a -= t * b; swap(a, b);
			u -= t * v; swap(u, v);
		}
		val = val * u % MOD;
		if (val < 0) val += MOD;
		return *this;
	}
	constexpr bool operator == (const Fp& r) const noexcept {
		return this->val == r.val;
	}
	constexpr bool operator != (const Fp& r) const noexcept {
		return this->val != r.val;
	}
	friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
		return os << x.val;
	}
	friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
		if (n == 0) return 1;
		auto t = modpow(a, n / 2);
		t = t * t;
		if (n & 1) t = t * a;
		return t;
	}
};

using mint = Fp<MOD>;

int main() {
	LL n; cin >> n;
	vector<vector<mint>> prev(210, vector<mint>(210));
	prev[0][0] = 1;

	for (int i = 0; i < n; i++) {
		char x; cin >> x;
		if (x == '-')continue;

		vector<vector<mint>> now(210, vector<mint>(210));
		if (x == 'D') {
			for (int j = 0; j <= n; j++) {
				for (int k = 0; k <= n; k++) {
					now[j][k] += prev[j+1][k+1] * (j+1)*(k+1);
					now[j+1][k]+=prev[j+1][k] * (j+1);
				}
			}
		}
		if (x == 'U') {
			for (int j = 0; j <= n; j++) {
				for (int k = 0; k <= n; k++) {
					now[j][k] += prev[j][k] * (k);
					now[j + 1][k + 1] += prev[j][k];
				}
			}
		}

		swap(now, prev);
	}

	cout << prev[0][0].val << endl;
	
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3924
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=int64_t;

constexpr ll mod = 1e9 + 7;

int main(){
  int n;
  cin >> n;
  vector<char> c;
  char ca;
  for(int i=0;i<n;i++){
    cin >> ca;
    if(ca=='-') continue;
    c.push_back(ca);
  }
  int n1=int(c.size());
  if(n1==0){
    cout << 1 << endl;
    return 0;
  }
  if((c[0]=='D')||(c[n1-1]=='U')){
    cout << 0 << endl;
    return 0;
  }
  
  vector dp(n1+1,vector<vector<ll>>(n1+1,vector<ll>(n1+1,0)));
  
  dp[1][1][1]=1;
  for(int i=1;i<n1;i++){
    for(int j=0;j<=i;j++){
      for(int k=j;k<=j;k++){
        if(dp[i][j][k]==0) continue;
        if(c[i]=='U'){
          (dp[i+1][j][k]+=(k*dp[i][j][k])%mod)%=mod;
          (dp[i+1][j+1][k+1]+=dp[i][j][k])%=mod;
        }else{
          (dp[i+1][j][k]+=(j*dp[i][j][k])%mod)%=mod;
          if(k!=0) (dp[i+1][j-1][k-1]+=(j*k*dp[i][j][k])%mod)%=mod;
        }
      }
      //cout << i << j << " " << dp[i][j][j] << endl;
    }
  }
  cout << dp[n1][0][0] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 63592
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define repd(i,a,b) for (ll 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<ll,ll> P;
typedef vector<ll> vec;
using Graph = vector<vector<ll>>;
const long long INF = 1LL<<60;
const long long MOD = 1000000007;

// auto mod int
// https://youtu.be/L8grWxBlIZ4?t=9858
// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
// https://youtu.be/8uowVvQ_-Mo?t=1329 : division
const int mod = 1000000007;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}

mint dp[205][205][205];

int main()
{  
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n;cin>>n;
    vector<char> c(n);
    rep(i,n)cin>>c[i];
    dp[0][0][0]=1;
    rep(i,n){
      rep(j,i+1)rep(k,i+1){
        if(c[i]=='-')dp[i+1][j+1][k+1]+=dp[i][j][k];
        else if(c[i]=='U'){
          dp[i+1][j][k]+=dp[i][j][k];
          dp[i+1][j+1][k+1]+=dp[i][j][k]*(i-k);
        }
        else{
          dp[i+1][j+1][k+1]+=dp[i][j][k]*(i-j);
          dp[i+1][j+2][k+2]+=dp[i][j][k]*(i-j)*(i-k);
        }
      }
    }
    cout<<dp[n][n][n]<<endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 70760
final_rank: 14

code_snippet: #include "bits/stdc++.h"

using namespace std;

using ll=long long;

using ll = long long;
using ull = unsigned long long;


constexpr unsigned mod = 1000000007;
struct Modint{
    unsigned num = 0;
    constexpr Modint() noexcept {}
    constexpr Modint(const Modint &x) noexcept : num(x.num){}
    inline constexpr operator ll() const noexcept { return num; }
    inline constexpr Modint& operator+=(Modint x) noexcept { num += x.num; if(num >= mod) num -= mod; return *this; }
    inline constexpr Modint& operator++() noexcept { if(num == mod - 1) num = 0; else num++; return *this; }
    inline constexpr Modint operator++(int) noexcept { Modint ans(*this); operator++(); return ans; }
    inline constexpr Modint operator-() const noexcept { return Modint(0) -= *this; }
    inline constexpr Modint operator-(Modint x) const noexcept { return Modint(*this) -= x; }
    inline constexpr Modint& operator-=(Modint x) noexcept { if(num < x.num) num += mod; num -= x.num; return *this; }
    inline constexpr Modint& operator--() noexcept { if(num == 0) num = mod - 1; else num--; return *this; }
    inline constexpr Modint operator--(int) noexcept { Modint ans(*this); operator--(); return ans; }
    inline constexpr Modint& operator*=(Modint x) noexcept { num = ull(num) * x.num % mod; return *this; }
    inline constexpr Modint& operator/=(Modint x) noexcept { return operator*=(x.inv()); }
    template<class T> constexpr Modint(T x) noexcept {
        using U = typename conditional<sizeof(T) >= 4, T, int>::type;
        U y = x; y %= U(mod); if(y < 0) y += mod; num = unsigned(y);
    }
    template<class T> inline constexpr Modint operator+(T x) const noexcept { return Modint(*this) += x; }
    template<class T> inline constexpr Modint& operator+=(T x) noexcept { return operator+=(Modint(x)); }
    template<class T> inline constexpr Modint operator-(T x) const noexcept { return Modint(*this) -= x; }
    template<class T> inline constexpr Modint& operator-=(T x) noexcept { return operator-=(Modint(x)); }
    template<class T> inline constexpr Modint operator*(T x) const noexcept { return Modint(*this) *= x; }
    template<class T> inline constexpr Modint& operator*=(T x) noexcept { return operator*=(Modint(x)); }
    template<class T> inline constexpr Modint operator/(T x) const noexcept { return Modint(*this) /= x; }
    template<class T> inline constexpr Modint& operator/=(T x) noexcept { return operator/=(Modint(x)); }
    inline constexpr Modint inv() const noexcept { ll x = 0, y = 0; extgcd(num, mod, x, y); return x; }
    static inline constexpr ll extgcd(ll a, ll b, ll &x, ll &y) noexcept { ll g = a; x = 1; y = 0; if(b){ g = extgcd(b, a % b, y, x); y -= a / b * x; } return g; }
    inline constexpr Modint pow(ull x) const noexcept { Modint ans = 1, cnt = *this; while(x){ if(x & 1) ans *= cnt; cnt *= cnt; x /= 2; } return ans; }
};
std::istream& operator>>(std::istream& is, Modint& x) noexcept { ll a; cin >> a; x = a; return is; }
inline constexpr Modint operator""_M(ull x) noexcept { return Modint(x); }
std::vector<Modint> fac(1, 1), inv(1, 1);
inline void reserve(ll a){
    if(fac.size() >= a) return;
    if(a < fac.size() * 2) a = fac.size() * 2;
    if(a >= mod) a = mod;
    while(fac.size() < a) fac.push_back(fac.back() * Modint(fac.size()));
    inv.resize(fac.size());
    inv.back() = fac.back().inv();
    for(ll i = inv.size() - 1; !inv[i - 1]; i--) inv[i - 1] = inv[i] * i;
}
inline Modint fact(ll n){ if(n < 0) return 0; reserve(n + 1); return fac[n]; }
inline Modint perm(ll n, ll r){
    if(r < 0 || n < r) return 0;
    if(n >> 24){ Modint ans = 1; for(ll i = 0; i < r; i++) ans *= n--; return ans; }
    reserve(n + 1); return fac[n] * inv[n - r];
}
inline Modint comb(ll n, ll r){ if(r < 0 || n < r) return 0; reserve(r + 1); return perm(n, r) * inv[r]; }
inline Modint Mcomb(ll n, ll r){ return comb(n + r - 1, n - 1); } // r個をn部屋に分ける
inline Modint catalan(ll n){ reserve(n * 2 + 1); return fac[n * 2] * inv[n] * inv[n + 1]; }

void solve(){
    int n;cin>>n;
    vector<char>c(n);
    for(auto &i:c)cin>>i;
    vector dp(n+1,vector<Modint>(n+1));
    dp[0][0]=1;
    //何個つかったか、使ってないUの個数
    for (int i = 0; i < n; ++i){
        vector ndp(n+1,vector<Modint>(n+1));
        if(c[i]=='-'){
            for (int j = 0; j <n; ++j) {
                for (int k = 0; k <=n; ++k) {
                    ndp[j+1][k]+=dp[j][k];
                }
            }
        }
        else {
            for (int j = 0; j <=i; ++j) {
                for (int k = 0; k <=n; ++k) {
                    if(c[i]=='D'){
                        if(j+1<=n)ndp[j+1][k]+=dp[j][k]*(i-j);
                        if(j+2<=n and k-1>=0)ndp[j+2][k-1]+=dp[j][k]*(i-j)*(i-j);
                    }
                    if(c[i]=='U'){
                        if(k+1<=n)ndp[j][k+1]+=dp[j][k];
                        if(j+1<=n)ndp[j+1][k]+=dp[j][k]*(i-j);
                    }
                }
            }
        }
        dp=move(ndp);
    }
    cout<<dp[n][0]<<"\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;
    while(t--){
        solve();
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3668
final_rank: 1

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

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;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi


#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder


namespace ebi {

using mint = atcoder::modint1000000007;

void main_() {
    int n;
    std::cin >> n;
    std::vector<char> c(n);
    rep(i,0,n) {
        std::cin >> c[i];
    }
    std::vector dp(n+1, std::vector<mint>(n+1, 0));
    dp[0][0] = 1;
    rep(i,0,n) {
        if(c[i] == '-') continue;
        std::vector nxt(n+1, std::vector<mint>(n+1, 0));
        rep(j,0,n+1) {
            rep(k,0,n+1) {
                if(c[i] == 'U') {
                    nxt[j][k] += dp[j][k] * j;
                    if(j + 1 <= n) {
                        if(k + 1 <= n) nxt[j+1][k+1] += dp[j][k];
                    }
                }
                else {
                    nxt[j][k] += dp[j][k] * k;
                    if(j > 0 && k > 0) {
                        nxt[j - 1][k - 1] += dp[j][k] * j * k;
                    }
                }
            }
        }
        dp = nxt;
    }
    std::cout << dp[0][0].val() << '\n';
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3768
final_rank: 8

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; // -2^63 ～ 2^63 = 9 * 10^18（int は -2^31 ～ 2^31 = 2 * 10^9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
const vi DX = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
const vi DY = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004004004004004LL;
double EPS = 1e-12;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), x))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), x))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0; set < (1 << int(d)); ++set) // d ビット全探索（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define smod(n, m) ((((n) % (m)) + (m)) % (m)) // 非負mod
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了

// 汎用関数の定義
template <class T> inline ll pow(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

// 手元環境（Visual Studio）
#ifdef _MSC_VER
#include "local.hpp"
// 提出用（gcc）
#else
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : -1; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : -1; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define gcd __gcd
#define dump(...)
#define dumpel(v)
#define dump_list(v)
#define dump_list2D(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) while (1) cout << "OLE"; }
#endif

#endif // 折りたたみ用


//#if __has_include(<atcoder/all>)
//#include <atcoder/all>
//using namespace atcoder;
//
//using mint = modint1000000007;
////using mint = modint998244353;
////using mint = modint; // mint::set_mod(m);
//
//istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
//ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
//using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;
//#endif


//【有限体 F_p 上の計算（32 bit）】
template <ll MOD> struct static_modint {
	ll v;

	// コンストラクタ
	static_modint() : v(0) {};
	static_modint(const static_modint& a) = default;
	static_modint(int a) : v(safe_mod(a)) {};
	static_modint(ll a) : v(safe_mod(a)) {};

	// 代入
	static_modint& operator=(const static_modint& a) { v = a.v; return *this; }
	static_modint& operator=(int a) { v = safe_mod(a); return *this; }
	static_modint& operator=(ll a) { v = safe_mod(a); return *this; }

	// 入出力
	friend istream& operator>> (istream& is, static_modint& x) { is >> x.v; x.v = safe_mod(x.v); return is; }
	friend ostream& operator<< (ostream& os, const static_modint& x) { os << x.v; return os; }

	// 非負 mod
	template <class T> static ll safe_mod(T a) { return (((ll)a % MOD) + MOD) % MOD; }

	// 比較
	bool operator==(const static_modint& b) const { return v == b.v; }
	bool operator==(int b) const { return v == safe_mod(b); }
	bool operator==(ll b) const { return v == safe_mod(b); }
	friend bool operator==(int a, const static_modint& b) { return b == a; }
	friend bool operator==(ll a, const static_modint& b) { return b == a; }
	bool operator!=(const static_modint& b) const { return v != b.v; }
	bool operator!=(int b) const { return v != safe_mod(b); }
	bool operator!=(ll b) const { return v != safe_mod(b); }
	friend bool operator!=(int a, const static_modint& b) { return b != a; }
	friend bool operator!=(ll a, const static_modint& b) { return b != a; }

	// 単項演算
	static_modint operator-() const { static_modint a = *this; return a *= -1; }
	static_modint& operator++() { v = safe_mod(v + 1); return *this; }
	static_modint operator++(int) { static_modint tmp = *this; ++(*this); return tmp; }
	static_modint& operator--() { v = safe_mod(v - 1); return *this; }
	static_modint operator--(int) { static_modint tmp = *this; --(*this); return tmp; }

	// 二項演算
	static_modint& operator+=(const static_modint& b) { v = safe_mod(v + b.v); return *this; }
	static_modint& operator-=(const static_modint& b) { v = safe_mod(v - b.v); return *this; }
	static_modint& operator*=(const static_modint& b) { v = safe_mod(v * b.v); return *this; }
	static_modint& operator/=(const static_modint& b) { *this *= b.inv(); return *this; }
	static_modint operator+(const static_modint& b) const { static_modint a = *this; return a += b; }
	static_modint operator-(const static_modint& b) const { static_modint a = *this; return a -= b; }
	static_modint operator*(const static_modint& b) const { static_modint a = *this; return a *= b; }
	static_modint operator/(const static_modint& b) const { static_modint a = *this; return a /= b; }

	// int との演算
	static_modint& operator+=(int b) { v = safe_mod(v + b); return *this; }
	static_modint& operator-=(int b) { v = safe_mod(v - b); return *this; }
	static_modint& operator*=(int b) { v = safe_mod(v * b); return *this; }
	static_modint& operator/=(int b) { *this *= static_modint(b).inv(); return *this; }
	static_modint operator+(int b) const { static_modint a = *this; return a += b; }
	static_modint operator-(int b) const { static_modint a = *this; return a -= b; }
	static_modint operator*(int b) const { static_modint a = *this; return a *= b; }
	static_modint operator/(int b) const { static_modint a = *this; return a /= b; }
	friend static_modint operator+(int a, const static_modint& b) { return b + a; }
	friend static_modint operator-(int a, const static_modint& b) { return -(b - a); }
	friend static_modint operator*(int a, const static_modint& b) { return b * a; }
	friend static_modint operator/(int a, const static_modint& b) { return b.inv() * a; }

	// ll との演算
	static_modint& operator+=(ll b) { v = safe_mod(v + (b % MOD)); return *this; }
	static_modint& operator-=(ll b) { v = safe_mod(v - (b % MOD)); return *this; }
	static_modint& operator*=(ll b) { v = safe_mod(v * (b % MOD)); return *this; }
	static_modint& operator/=(ll b) { *this *= static_modint(b).inv(); return *this; }
	static_modint operator+(ll b) const { static_modint a = *this; return a += b; }
	static_modint operator-(ll b) const { static_modint a = *this; return a -= b; }
	static_modint operator*(ll b) const { static_modint a = *this; return a *= b; }
	static_modint operator/(ll b) const { static_modint a = *this; return a /= b; }
	friend static_modint operator+(ll a, const static_modint& b) { return b + a; }
	friend static_modint operator-(ll a, const static_modint& b) { return -(b - a); }
	friend static_modint operator*(ll a, const static_modint& b) { return b * a; }
	friend static_modint operator/(ll a, const static_modint& b) { return b.inv() * a; }

	// 累乗（0^0 := 1）
	static_modint pow(ll d) const {
		static_modint res(1), pow2 = *this;
		while (d > 0) {
			if (d & 1LL) res *= pow2;
			pow2 *= pow2;
			d /= 2;
		}
		return res;
	}

	// 逆元（0^(-1) は未定義）
	static_modint inv() const {
		Assert(v != 0);
		return pow(MOD - 2);
	}

	// 法の確認
	static int mod() { return MOD; }

	// 値の確認
	int val() const { return int(v); }
};
using mint = static_modint<1000000007>;
//using mint = static_modint<998244353>;
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;


//【階乗など（法が大きな素数）】
/*
* Factorial_mint(int n_max) : O(n_max)
*	n_max! まで計算可能として初期化する．
*
* mint factorial(int n) : O(1)
*	n! を返す．
*
* mint factorial_inv(int n) : O(1)
*	1 / n! を返す．
*
* mint inv(int n) : O(1)
*	1 / n を返す．
*
* mint permutation(int n, int r) : O(1)
*	順列の数 nPr を返す．
*
* mint binomial(int n, int r) : O(1)
*	二項係数 nCr を返す．
*
* mint multinomial(vi rs) : O(|rs|)
*	多項係数 nC[rs] を返す．（n = Σrs）
*/
class Factorial_mint {
	// 階乗，階乗の逆数，逆数の値を保持するテーブル
	int n_max;
	vm fac, fac_inv;

public:
	// n! までの階乗とその逆数を前計算しておく．O(n)
	Factorial_mint(int n) : n_max(n), fac(n + 1), fac_inv(n + 1) {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		fac[0] = 1;
		repi(i, 1, n) fac[i] = fac[i - 1] * i;

		fac_inv[n] = fac[n].inv();
		repir(i, n - 1, 0) fac_inv[i] = fac_inv[i + 1] * (i + 1);
	}
	Factorial_mint() : n_max(0) {} // ダミー

	// n! を返す．O(1)
	mint factorial(int n) const {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		Assert(0 <= n && n <= n_max);
		return fac[n];
	}

	// 1 / n! を返す．O(1)
	mint factorial_inv(int n) const {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		Assert(0 <= n && n <= n_max);
		return fac_inv[n];
	}

	// 1 / n を返す．O(1)
	mint inv(int n) const {
		// verify : https://atcoder.jp/contests/exawizards2019/tasks/exawizards2019_d

		Assert(0 < n && n <= n_max);
		return fac[n - 1] * fac_inv[n];
	}

	// 順列の数 nPr を返す．O(1)
	mint permutation(int n, int r) const {
		Assert(n <= n_max);

		if (r < 0 || n - r < 0) return 0;
		return fac[n] * fac_inv[n - r];
	}

	// 二項係数 nCr を返す．O(1)
	mint binomial(int n, int r) const {
		// verify : https://atcoder.jp/contests/abc034/tasks/abc034_c

		Assert(n <= n_max);
		if (r < 0 || n - r < 0) return 0;
		return fac[n] * fac_inv[r] * fac_inv[n - r];
	}

	// 多項係数 nC[r] を返す．O(|r|)
	mint multinomial(const vi& rs) const {
		// verify : https://yukicoder.me/problems/no/2141

		if (*min_element(all(rs)) < 0) return 0;
		int n = accumulate(all(rs), 0);
		Assert(n <= n_max);

		mint res = fac[n];
		repe(r, rs) res *= fac_inv[r];

		return res;
	}
};


//【上下限の指定された順列の数え上げ】O(n^3)
/*
* [0..n) の順列 p[0..n) のうち，p[0..nu) <= ub[0..nu), p[nu..nu+nl) >= lb[0..nl) (nu + nl = n)
* を満たすものの個数を返す．
*
* 利用：【階乗など（法が大きな素数）】
*/
mint count_permutations_single_bound(const vi& ub, const vi& lb) {
	int nu = sz(ub), nl = sz(lb), n = nu + nl;

	// ub_cnt[i] : 上界が i であると指定されている p の要素の個数
	vi ub_cnt(n);
	rep(j, nu) {
		if (ub[j] < 0) return 0;
		ub_cnt[min(ub[j], n - 1)]++;
	}

	// lb_cnt[i] : 下界が v であると指定されている p の要素の個数
	vi lb_cnt(n);
	rep(k, nl) {
		if (lb[k] >= n) return 0;
		lb_cnt[max(lb[k], 0)]++;
	}

	Factorial_mint fm(n);

	dump(ub_cnt); dump(lb_cnt);

	// dp_i[j][k] : [0..i) までの数について，
	//	p[0..nu) のいずれかに割り当てることだけが決まっている数が j 個，
	//	p[nu..nu+nl) の中の割り当て待ちの数が k 個ある場合の数
	vvm dp(nu + 1, vm(nl + 1));
	dp[0][0] = 1;

	rep(i, n) {
		vvm dp2(nu + 1, vm(nl + 1));
		repi(j, 0, nu) repi(k, 0, nl - lb_cnt[i]) {
			// 下界が i だと指定されている数が lb_cnt[i] 個あるので，
			// p[nu..nu+nl) の中の割り当て待ちの数がそれだけ増加する．
			dp2[j][k + lb_cnt[i]] += dp[j][k];
		}

		vvm dp3(nu + 1, vm(nl + 1));
		repi(j, 0, nu) repi(k, 0, nl) {
			// i を p[0..nu) のいずれかに割り当てる予約をする場合
			if (j < nu) dp3[j + 1][k] += dp2[j][k];

			// i を p[nu..nu+nl) のいずれかに確定的に割り当てる場合
			if (k > 0) dp3[j][k - 1] += k * dp2[j][k];
		}

		dp = vvm(nu + 1, vm(nl + 1));
		repi(j, ub_cnt[i], nu) repi(k, 0, nl) {
			// p[0..nu) に割り当てることだけが決まっていた未確定の j 個の数のうち，
			// 上界が i だと指定されている ub_cnt[i] 個だけ具体的な数を確定させる．
			dp[j - ub_cnt[i]][k] += dp3[j][k] * fm.permutation(j, ub_cnt[i]);
		}

		dumpel(dp);
	}

	return dp[0][0];
}


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

	int n;
	cin >> n;

	vc c(n);
	cin >> c;

	vc c2;
	repe(x, c) if (x != '-') c2.push_back(x);

	int n2 = sz(c2);
	if (n2 == 0) EXIT(1);

	vi ub, lb;
	rep(i, n2) {
		if (c2[i] == 'U') lb.push_back(i + 1);
		else ub.push_back(i - 1);
	}

	cout << count_permutations_single_bound(ub, lb) << endl;

	//int n;
	//cin >> n;

	//vi ub, lb;
	//rep(i, n) {
	//	int t, x;
	//	cin >> t >> x;
	//	x--;

	//	if (t) lb.push_back(x);
	//	else ub.push_back(x);
	//}

	//cout << count_permutations_single_bound(ub, lb) << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 3752
final_rank: 7

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

typedef long long ll; typedef unsigned long long ull;
const int inf = 1e9; const ll llnf = 4e18;

template< class Tp > void chkmax( Tp &x , Tp y ) { x = max( x , y ); }
template< class Tp > void chkmin( Tp &x , Tp y ) { x = min( x , y ); }

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using modint = atcoder::modint1000000007;

void solve( ) {
	int n; cin >> n; vector< int > a{ 0 };
	for( int i = 1; i <= n; i ++ ) { char ch; cin >> ch; if( ch != '-' ) a.emplace_back( ch == 'U' ); }
	int N = ( int ) a.size( ) - 1;

	vector< vector< vector< modint > > > f( N + 1 , vector< vector< modint > >( N + 1 , vector< modint >( N + 1 ) ) ); f[0][0][0] = 1;
	for( int i = 0; i < N; i ++ ) for( int p = 0; p <= i; p ++ ) for( int q = 0; q <= i; q ++ ) if( f[i][p][q].val( ) ) {
		if( a[i + 1] ) {
			f[i + 1][p + 1][q + 1] += f[i][p][q] , f[i + 1][p][q] += f[i][p][q] * p;
		} else {
			( p && q ) && ( f[i + 1][p - 1][q - 1] += f[i][p][q] * p * q , true ) , f[i + 1][p][q] += f[i][p][q] * q;
		}
	}
	cout << f[N][0][0].val( ) << "\n";
}

int main( ) {
	ios::sync_with_stdio( 0 ), cin.tie( 0 ), cout.tie( 0 );
	int T = 1; while( T -- ) solve( ); return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 34220
final_rank: 11

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

const long long mod = (int) 1e9 + 7;

void add(long long &a, long long b) {
    a += b;
    a %= mod;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    vector<string> c;
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        if (s != "-") {
            c.emplace_back(s);
        }
    }
    n = (int) c.size();
    vector<vector<long long>> dp(n + 1, vector<long long>(n + 1));
    dp[0][0] = 1;
    for (auto s : c) {
        vector<vector<long long>> new_dp(n + 1, vector<long long>(n + 1));
        for (int x = 0; x < n; x++) {
            for (int y = 0; y < n; y++) {
                if (s == "D") {
                    if (x > 0) {
                        if (y > 0) {
                            add(new_dp[x - 1][y - 1], dp[x][y] * x * y);
                        }
                        add(new_dp[x][y], dp[x][y] * x);
                    }
                } else {
                    if (y > 0) {
                        add(new_dp[x][y], dp[x][y] * y);
                    }
                    add(new_dp[x + 1][y + 1], dp[x][y]);
                }
            }
        }
        swap(dp, new_dp);
    }
    cout << dp[0][0] << "\n";
}
accuracy: 1
time_ms: 50
memory_kb: 3696
final_rank: 10

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

using ll = long long;
using ull = unsigned long long;
using ld = long double;
template<class t> using vc = vector<t>;
template<class t> using vvc = vc<vc<t>>;
using pi = pair<int,int>;
using pl = pair<ll,ll>;
using vi = vc<int>;
using vvi = vvc<int>;
using vl = vc<ll>;
using vvl = vvc<ll>;

#define rep(i,a,b) for (int i = (int)(a); i < (int)(b); i++)
#define irep(i,a,b) for (int i = (int)(a); i > (int)(b); i--)
#define all(a) a.begin(),a.end()
#define print(n) cout << n << '\n'
#define pritn(n) print(n)
#define printv(n,a) {copy(all(n),ostream_iterator<a>(cout," ")); cout<<"\n";}
#define printvv(n,a) {for(auto itr:n) printv(itr,a);}
#define rup(a,b) (a+b-1)/b
#define input(A,N) rep(i,0,N) cin>>A[i]
#define chmax(a,b) a = max(a,b)
#define chmin(a,b) a = min(a,b)

//const ll mod = 998'244'353;
const ll mod = 1'000'000'007;
//const ll mod = 67'280'421'310'721;
struct mint{
    long long x;
    mint(long long x=0):x((x%mod+mod)%mod){}
    mint operator-() const{
        return mint(-x);
    }
    mint& operator+=(const mint& a){
        if((x+=a.x)>=mod)x-=mod;
        return *this;
    }
    mint& operator-=(const mint& a){
        if((x+=mod-a.x)>=mod)x-=mod;
        return *this;
    }
    mint& operator*=(const  mint& a){
        (x *= a.x) %= mod;
        return *this;
    }
    mint operator+(const mint& a) const{
        mint res(*this);
        return res+=a;
    }
    mint operator-(const mint& a) const{
        mint res(*this);
        return res-=a;
    }
    mint operator*(const mint& a) const{
        mint res(*this);
        return res*=a;
    }
    mint pow(long long n) const {
        assert(0 <= n);
        mint a = *this, r = 1;
        while (n) {
            if (n & 1) r *= a;
            a *= a;
            n >>= 1;
        }
        return r;
    }
    mint inv() const{
        return pow(mod-2);
    }
    mint& operator/=(const mint& a){
        return (*this)*=a.inv();
    }
    mint operator/(const mint& a) const {
        mint res(*this);
        return res/=a;
    }
    friend ostream& operator<<(ostream& os, const mint& m){
        os << m.x;
        return os;
    }
    bool operator==(const mint& a) const {
        return x == a.x;
    }
    bool operator<(const mint& a) const{
        return x < a.x;
    }
};


int main(){
    cout << fixed << setprecision(15);
    
    int n;
    cin>>n;
    vc<char> c(n);
    input(c,n);
    vc<mint> fac(n+1,1);
    rep(i,1,n+1) fac[i] = fac[i-1] * mint(i);
    vc<vvc<mint>> dp(n+1,vvc<mint>(n+1,vc<mint>(n+1,0)));
    dp[0][0][0] = 1;
    for(int i = 0;i<n;i++){
        if(c[i]=='-'){
            for(int j = 0;j<=n;j++){
                for(int k = 0;k<=n;k++){
                    dp[i+1][j][k] = dp[i][j][k];
                }
            }
            continue;
        }
        vvc<mint> now(n+1,vc<mint>(n+1,0));
        if(c[i]=='D'){
            for(int j = 1;j<=n;j++){
                for(int k = 0;k<=n;k++){
                    now[j-1][k] += dp[i][j][k] * mint(j);
                }
            }            
            for(int j = 0;j<n;j++){
                for(int k = 0;k<=n;k++){
                    dp[i+1][j+1][k] += now[j][k];
                }
            }
            for(int j = 0;j<=n;j++){
                for(int k = 1;k<=n;k++){
                    dp[i+1][j][k-1] += now[j][k] * mint(k);
                }
            }
        }else{
            for(int j = 0;j<n;j++){
                for(int k = 0;k<=n;k++){
                    now[j+1][k] += dp[i][j][k];
                }
            }
            for(int j = 0;j<=n;j++){
                for(int k = 1;k<=n;k++){
                    now[j][k-1] += dp[i][j][k] * mint(k);
                }
            }
            for(int j = 0;j<=n;j++){
                for(int k = 0;k<n;k++){
                    dp[i+1][j][k+1] += now[j][k];
                }
            }
        }
    }
    print(dp[n][0][0]);
    //printvv(dp[n],mint);
    
    //system("pause");
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 67880
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
#endif

namespace ttl{

using namespace std;
using f80=long double;
using i64=int64_t;
using u64=uint64_t;

template<int mod> struct mymodint{
  i64 vl;
  static constexpr i64 get_mod(){ return mod; }
  i64 val(){ return vl; }
  mymodint(i64 vl_=0):vl(vl_%mod){}
  mymodint operator-(){ return (vl==0)?0:mod-vl; }
  mymodint operator+(mymodint rhs){ return mymodint(*this)+=rhs; }
  mymodint operator-(mymodint rhs){ return mymodint(*this)-=rhs; }
  mymodint operator*(mymodint rhs){ return mymodint(*this)*=rhs; }
  mymodint operator/(mymodint rhs){ return mymodint(*this)/=rhs; }
  mymodint pow(i64 rhs){
    mymodint res=1,now=(*this);
    while(rhs){
      res*=((rhs&1)?now:1),now*=now,rhs>>=1;
    }
    return res;
  }
  mymodint& operator+=(mymodint rhs){
    vl+=rhs.vl,vl-=((vl>=mod)?mod:0);
    return (*this);
  }
  mymodint& operator-=(mymodint rhs){
    vl+=((vl<rhs.vl)?mod:0),vl-=rhs.vl;
    return (*this);
  }
  mymodint& operator*=(mymodint rhs){
    vl=vl*rhs.vl%mod;
    return (*this);
  }
  mymodint& operator/=(mymodint rhs){ return (*this)*=rhs.pow(mod-2); }
  bool operator==(mymodint rhs){ return vl==rhs.vl; }
  bool operator!=(mymodint rhs){ return vl!=rhs.vl; }
};

template<u64 mod> using modint=
#if __has_include(<atcoder/all>)
  atcoder::static_modint<mod>;
#else
  mymodint<mod>;
#endif

template<int mod> std::ostream& operator<<(std::ostream& os,modint<mod> x){
  return os<<(x.val());
}
template<int mod> std::istream& operator>>(std::istream& is,modint<mod>& x){
  i64 t;
  is>>t,x=t;
  return is;
}

template<class T> void scn_(T& a){ cin>>a; }
template<class T,class U> void scn_(pair<T,U>& a){ scn_(a.first),scn_(a.second); }
template<class T> void scn_(vector<T>& a){
  for(auto& v:a){
    scn_(v);
  }
}
template<class T> void scn_(vector<vector<T>>& a){
  for(auto& v:a){
    for(auto& u:v){
      cin>>u;
    }
  }
}
void scn(){}
template<class T,class... Args> void scn(T& n,Args&... args){ scn_(n),scn(args...); }
template<class T> void prt_(T a){ cout<<a; }
template<class T,class U> void prt_(pair<T,U> a){ cout<<"{"<<a.first<<", "<<a.second<<"}"; }
void prt_(f80 a){ printf("%.15Lf",a); }
template<class T> void prt(vector<T> a){
  for(size_t i=0;i<a.size();++i){
    prt_(a[i]);
    cout<<" \n"[i==a.size()-1];
  }
}
template<class T> void prt(vector<vector<T>> a){
  for(auto& v:a){
    for(size_t i=0;i<v.size();++i){
      cout<<v[i]<<" \n"[i==v.size()-1];
    }
  }
}
template<class T> void prt(T a){ prt_(a),cout<<"\n"; }
template<class T,class... Args> void prt(T a,Args... args){ prt_(a),cout<<" ",prt(args...); }

template<class Head,class... Tail> struct multi_dim_vector{ using type=vector<typename multi_dim_vector<Tail...>::type>; };
template<class T> struct multi_dim_vector<T>{ using type=T; };
template<class T,class Arg> vector<T> mvec(int n,Arg&& arg){ return vector<T>(n,arg); }
template<class T,class... Args> class multi_dim_vector<Args...,T>::type mvec(int n,Args&&... args){
  return typename multi_dim_vector<Args...,T>::type(n,mvec<T>(args...));
}

template<class T> void rev(T& a){ reverse(a.begin(),a.end());}
template<class T> void srt(T& a){ sort(a.begin(),a.end()); }
template<class T> void rsrt(T& a){ sort(a.rbegin(),a.rend()); }
template<class T> T revd(T a){
  reverse(a.begin(),a.end());
  return a;
}
template<class T> T srtd(T a){
  sort(a.begin(),a.end());
  return a;
}
template<class T> T rsrtd(T a){
  sort(a.rbegin(),a.rend());
  return a;
}
template<class T> T summ(vector<T> a){ return accumulate(a.begin(),a.end(),T(0)); }
template<class T> T maxi(vector<T> a){ return *max_element(a.begin(),a.end()); }
template<class T> T mini(vector<T> a){ return *min_element(a.begin(),a.end()); }
template<class T> void chmx(T& a,T b){ a=max(a,b); }
template<class T> void chmn(T& a,T b){ a=min(a,b); }
i64 ppcnt(u64 k){ return __builtin_popcountll(k); }
template<class T> T powe(T a,i64 n){
  T res=1;
  while(n){
    if(n&1){ res*=a; }
    a*=a;
    n/=2;
  }
  return res;
}
i64 powe(i64 a,i64 n,i64 m){
  i64 res=1;
  while(n){
    if(n&1){ res=res*a%m; }
    a=a*a%m;
    n/=2;
  }
  return res;
}
template<class T> void zip(vector<T>& a){
  auto b=srtd(a);
  b.erase(unique(b.begin(),b.end()),b.end());
  map<T,int> mp;
  for(int i=0;i<b.size();++i){
    mp[b[i]]=i;
  }
  for(auto& v:a){
    v=mp[v];
  }
}
i64 sqrf(i64 n){
  i64 ok=0,ng=1e9+5;
  while(std::abs(ok-ng)>1){
    i64 mid=(ok+ng)/2;
    (mid*mid<=n?ok:ng)=mid;
  }
  return ok;
}
i64 sqrc(i64 n){
  i64 ok=1e9+5,ng=0;
  while(std::abs(ok-ng)>1){
    i64 mid=(ok+ng)/2;
    (mid*mid>=n?ok:ng)=mid;
  }
  return ok;
}
i64 dvf(i64 a,i64 b){
  if(b<0){ a*=-1,b*=-1; }
  if(a<0){ return -(-a+b-1)/b; }
  return a/b;
}
i64 dvc(i64 a,i64 b){
  if(b<0){ a*=-1,b*=-1; }
  if(a<0){ return -(-a)/b; }
  return (a+b-1)/b;
}
vector<int> bfs(vector<vector<int>> G,int v){
  int N=G.size();
  vector<int> dst(N,-1);
  queue<int> q;
  dst[v]=0;
  q.emplace(v);
  while(q.size()){
    int t=q.front();
    q.pop();
    for(auto u:G[t]){
      if(dst[u]==-1){
        dst[u]=dst[t]+1;
        q.emplace(u);
      }
    }
  }
  return dst;
}
vector<i64> dijkstra(vector<vector<pair<int,i64>>>& G,int s){
  int N=G.size();
  vector<i64> dst(N,1e18);
  dst[s]=0;
  priority_queue<pair<i64,int>,vector<pair<i64,int>>,greater<pair<i64,int>>> pq;
  pq.emplace(0,s);
  vector<int> f(N);
  while(pq.size()){
    auto [t,u]=pq.top();
    pq.pop();
    if(f[u]){ continue; }
    f[u]=1;
    for(auto [v,w]:G[u]){
      if(dst[v]>dst[u]+w){
        dst[v]=dst[u]+w;
        pq.emplace(dst[v],v);
      }
    }
  }
  return dst;
}
vector<pair<i64,i64>> pfct(i64 n){
  vector<pair<i64,i64>> res;
  for(i64 i=2;i*i<=n;++i){
    if(n%i!=0){ continue; }
    i64 ex=0;
    while(n%i==0){ ex++,n/=i; }
    res.emplace_back(i,ex);
  }
  if(n!=1){ res.emplace_back(n,1); }
  return res;
}
vector<i64> ediv(i64 n){
  vector<i64> res;
  for(i64 i=1;i*i<=n;++i){
    if(n%i!=0){ continue; }
    res.emplace_back(i);
    if(i*i!=n){ res.emplace_back(n/i); }
  }
  srt(res);
  return res;
}
template<class T> struct csm2d{
  int n,m;
  vector<vector<T>> a,c;
  csm2d(vector<vector<T>> a_):n(a_.size()),m(a_[0].size()),a(a_){
    auto b=mvec<T>(n,m+1,0);
    for(int i=0;i<n;++i){
      for(int j=0;j<m;++j){
        b[i][j+1]=b[i][j]+a[i][j];
      }
    }
    c=mvec<T>(n+1,m+1,0);
    for(int j=0;j<m+1;++j){
      for(int i=0;i<n;++i){
        c[i+1][j]=c[i][j]+b[i][j];
      }
    }
  }
  T operator()(int p,int q,int r,int s){
    return c[p][r]-c[p][s]-c[q][r]+c[q][s];
  }
};
template<class T> auto runlng(T a) -> vector<pair<typename decltype(a)::value_type,i64>>{
  int n=a.size();
  vector<pair<typename decltype(a)::value_type,i64>> res;
  typename decltype(a)::value_type now=a[0];
  i64 l=1;
  for(int i=1;i<n;++i){
    if(a[i-1]==a[i]){ l++; }
    else{
      res.emplace_back(now,l);
      now=a[i],l=1;
    }
  }
  res.emplace_back(now,l);
  return res;
}
template<class T> struct cmb{
  vector<T> fac,ifac;
  cmb(int mx=3000000):fac(mx+1,1),ifac(mx+1,1){
    for(int i=1;i<=mx;++i){ fac[i]=fac[i-1]*i; }
    ifac[mx]/=fac[mx];
    for(int i=mx;i>0;--i){ ifac[i-1]=ifac[i]*i; }
  }
  T operator()(int n,int k){
    if(n<0||k<0||n<k){ return 0; }
    return fac[n]*ifac[k]*ifac[n-k];
  }
};

}

using namespace ttl;

int main(){
  constexpr int mod=1000000007;
  using mint=modint<mod>;
  cmb<mint> Cb;
  int N;
  scn(N);
  vector<char> c(N);
  for(int i=0;i<N;++i){
    scn(c[i]);
  }
  auto dp=mvec<mint>(N+1,N+1,0);
  dp[0][0]=1;
  //dp[i][j] := i まで来てマッチングしてないのが j
  for(int i=0;i<N;++i){
    for(int j=0;j<N;++j){
      if(c[i]=='-'){ dp[i+1][j]+=dp[i][j]; }
      if(c[i]=='U'){ dp[i+1][j+1]+=dp[i][j],dp[i+1][j]+=dp[i][j]*j; }
      if(c[i]=='D'){ if(0<j){ dp[i+1][j-1]+=dp[i][j]*j*j,dp[i+1][j]+=dp[i][j]*j; } }
    }
  }
  prt(dp[N][0]);
}
accuracy: 1
time_ms: 20
memory_kb: 50184
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
#endif

namespace ttl{

using namespace std;
using f80=long double;
using i64=int64_t;
using u64=uint64_t;

template<int mod> struct mymodint{
  i64 vl;
  static constexpr i64 get_mod(){ return mod; }
  i64 val(){ return vl; }
  mymodint(i64 vl_=0):vl(vl_%mod){}
  mymodint operator-(){ return (vl==0)?0:mod-vl; }
  mymodint operator+(mymodint rhs){ return mymodint(*this)+=rhs; }
  mymodint operator-(mymodint rhs){ return mymodint(*this)-=rhs; }
  mymodint operator*(mymodint rhs){ return mymodint(*this)*=rhs; }
  mymodint operator/(mymodint rhs){ return mymodint(*this)/=rhs; }
  mymodint pow(i64 rhs){
    mymodint res=1,now=(*this);
    while(rhs){
      res*=((rhs&1)?now:1),now*=now,rhs>>=1;
    }
    return res;
  }
  mymodint& operator+=(mymodint rhs){
    vl+=rhs.vl,vl-=((vl>=mod)?mod:0);
    return (*this);
  }
  mymodint& operator-=(mymodint rhs){
    vl+=((vl<rhs.vl)?mod:0),vl-=rhs.vl;
    return (*this);
  }
  mymodint& operator*=(mymodint rhs){
    vl=vl*rhs.vl%mod;
    return (*this);
  }
  mymodint& operator/=(mymodint rhs){ return (*this)*=rhs.pow(mod-2); }
  bool operator==(mymodint rhs){ return vl==rhs.vl; }
  bool operator!=(mymodint rhs){ return vl!=rhs.vl; }
};

template<u64 mod> using modint=
#if __has_include(<atcoder/all>)
  atcoder::static_modint<mod>;
#else
  mymodint<mod>;
#endif

template<int mod> std::ostream& operator<<(std::ostream& os,modint<mod> x){
  return os<<(x.val());
}
template<int mod> std::istream& operator>>(std::istream& is,modint<mod>& x){
  i64 t;
  is>>t,x=t;
  return is;
}

template<class T> void scn_(T& a){ cin>>a; }
template<class T,class U> void scn_(pair<T,U>& a){ scn_(a.first),scn_(a.second); }
template<class T> void scn_(vector<T>& a){
  for(auto& v:a){
    scn_(v);
  }
}
template<class T> void scn_(vector<vector<T>>& a){
  for(auto& v:a){
    for(auto& u:v){
      cin>>u;
    }
  }
}
void scn(){}
template<class T,class... Args> void scn(T& n,Args&... args){ scn_(n),scn(args...); }
template<class T> void prt_(T a){ cout<<a; }
template<class T,class U> void prt_(pair<T,U> a){ cout<<"{"<<a.first<<", "<<a.second<<"}"; }
void prt_(f80 a){ printf("%.15Lf",a); }
template<class T> void prt(vector<T> a){
  for(size_t i=0;i<a.size();++i){
    prt_(a[i]);
    cout<<" \n"[i==a.size()-1];
  }
}
template<class T> void prt(vector<vector<T>> a){
  for(auto& v:a){
    for(size_t i=0;i<v.size();++i){
      cout<<v[i]<<" \n"[i==v.size()-1];
    }
  }
}
template<class T> void prt(T a){ prt_(a),cout<<"\n"; }
template<class T,class... Args> void prt(T a,Args... args){ prt_(a),cout<<" ",prt(args...); }

template<class Head,class... Tail> struct multi_dim_vector{ using type=vector<typename multi_dim_vector<Tail...>::type>; };
template<class T> struct multi_dim_vector<T>{ using type=T; };
template<class T,class Arg> vector<T> mvec(int n,Arg&& arg){ return vector<T>(n,arg); }
template<class T,class... Args> class multi_dim_vector<Args...,T>::type mvec(int n,Args&&... args){
  return typename multi_dim_vector<Args...,T>::type(n,mvec<T>(args...));
}

template<class T> void rev(T& a){ reverse(a.begin(),a.end());}
template<class T> void srt(T& a){ sort(a.begin(),a.end()); }
template<class T> void rsrt(T& a){ sort(a.rbegin(),a.rend()); }
template<class T> T revd(T a){
  reverse(a.begin(),a.end());
  return a;
}
template<class T> T srtd(T a){
  sort(a.begin(),a.end());
  return a;
}
template<class T> T rsrtd(T a){
  sort(a.rbegin(),a.rend());
  return a;
}
template<class T> T summ(vector<T> a){ return accumulate(a.begin(),a.end(),T(0)); }
template<class T> T maxi(vector<T> a){ return *max_element(a.begin(),a.end()); }
template<class T> T mini(vector<T> a){ return *min_element(a.begin(),a.end()); }
template<class T> void chmx(T& a,T b){ a=max(a,b); }
template<class T> void chmn(T& a,T b){ a=min(a,b); }
i64 ppcnt(u64 k){ return __builtin_popcountll(k); }
template<class T> T powe(T a,i64 n){
  T res=1;
  while(n){
    if(n&1){ res*=a; }
    a*=a;
    n/=2;
  }
  return res;
}
i64 powe(i64 a,i64 n,i64 m){
  i64 res=1;
  while(n){
    if(n&1){ res=res*a%m; }
    a=a*a%m;
    n/=2;
  }
  return res;
}
template<class T> void zip(vector<T>& a){
  auto b=srtd(a);
  b.erase(unique(b.begin(),b.end()),b.end());
  map<T,int> mp;
  for(int i=0;i<b.size();++i){
    mp[b[i]]=i;
  }
  for(auto& v:a){
    v=mp[v];
  }
}
i64 sqrf(i64 n){
  i64 ok=0,ng=1e9+5;
  while(std::abs(ok-ng)>1){
    i64 mid=(ok+ng)/2;
    (mid*mid<=n?ok:ng)=mid;
  }
  return ok;
}
i64 sqrc(i64 n){
  i64 ok=1e9+5,ng=0;
  while(std::abs(ok-ng)>1){
    i64 mid=(ok+ng)/2;
    (mid*mid>=n?ok:ng)=mid;
  }
  return ok;
}
i64 dvf(i64 a,i64 b){
  if(b<0){ a*=-1,b*=-1; }
  if(a<0){ return -(-a+b-1)/b; }
  return a/b;
}
i64 dvc(i64 a,i64 b){
  if(b<0){ a*=-1,b*=-1; }
  if(a<0){ return -(-a)/b; }
  return (a+b-1)/b;
}
vector<int> bfs(vector<vector<int>> G,int v){
  int N=G.size();
  vector<int> dst(N,-1);
  queue<int> q;
  dst[v]=0;
  q.emplace(v);
  while(q.size()){
    int t=q.front();
    q.pop();
    for(auto u:G[t]){
      if(dst[u]==-1){
        dst[u]=dst[t]+1;
        q.emplace(u);
      }
    }
  }
  return dst;
}
vector<i64> dijkstra(vector<vector<pair<int,i64>>>& G,int s){
  int N=G.size();
  vector<i64> dst(N,1e18);
  dst[s]=0;
  priority_queue<pair<i64,int>,vector<pair<i64,int>>,greater<pair<i64,int>>> pq;
  pq.emplace(0,s);
  vector<int> f(N);
  while(pq.size()){
    auto [t,u]=pq.top();
    pq.pop();
    if(f[u]){ continue; }
    f[u]=1;
    for(auto [v,w]:G[u]){
      if(dst[v]>dst[u]+w){
        dst[v]=dst[u]+w;
        pq.emplace(dst[v],v);
      }
    }
  }
  return dst;
}
vector<pair<i64,i64>> pfct(i64 n){
  vector<pair<i64,i64>> res;
  for(i64 i=2;i*i<=n;++i){
    if(n%i!=0){ continue; }
    i64 ex=0;
    while(n%i==0){ ex++,n/=i; }
    res.emplace_back(i,ex);
  }
  if(n!=1){ res.emplace_back(n,1); }
  return res;
}
vector<i64> ediv(i64 n){
  vector<i64> res;
  for(i64 i=1;i*i<=n;++i){
    if(n%i!=0){ continue; }
    res.emplace_back(i);
    if(i*i!=n){ res.emplace_back(n/i); }
  }
  srt(res);
  return res;
}
template<class T> struct csm2d{
  int n,m;
  vector<vector<T>> a,c;
  csm2d(vector<vector<T>> a_):n(a_.size()),m(a_[0].size()),a(a_){
    auto b=mvec<T>(n,m+1,0);
    for(int i=0;i<n;++i){
      for(int j=0;j<m;++j){
        b[i][j+1]=b[i][j]+a[i][j];
      }
    }
    c=mvec<T>(n+1,m+1,0);
    for(int j=0;j<m+1;++j){
      for(int i=0;i<n;++i){
        c[i+1][j]=c[i][j]+b[i][j];
      }
    }
  }
  T operator()(int p,int q,int r,int s){
    return c[p][r]-c[p][s]-c[q][r]+c[q][s];
  }
};
template<class T> auto runlng(T a) -> vector<pair<typename decltype(a)::value_type,i64>>{
  int n=a.size();
  vector<pair<typename decltype(a)::value_type,i64>> res;
  typename decltype(a)::value_type now=a[0];
  i64 l=1;
  for(int i=1;i<n;++i){
    if(a[i-1]==a[i]){ l++; }
    else{
      res.emplace_back(now,l);
      now=a[i],l=1;
    }
  }
  res.emplace_back(now,l);
  return res;
}
template<class T> struct cmb{
  vector<T> fac,ifac;
  cmb(int mx=3000000):fac(mx+1,1),ifac(mx+1,1){
    for(int i=1;i<=mx;++i){ fac[i]=fac[i-1]*i; }
    ifac[mx]/=fac[mx];
    for(int i=mx;i>0;--i){ ifac[i-1]=ifac[i]*i; }
  }
  T operator()(int n,int k){
    if(n<0||k<0||n<k){ return 0; }
    return fac[n]*ifac[k]*ifac[n-k];
  }
};

}

using namespace ttl;

int main(){
  constexpr int mod=998244353;
  using mint=modint<mod>;
  cmb<mint> Cb;
  int N;
  scn(N);
  vector<char> c(N);
  for(int i=0;i<N;++i){
    scn(c[i]);
  }
  auto dp=mvec<mint>(N+1,N+1,0);
  dp[0][0]=1;
  //dp[i][j] := i まで来てマッチングしてないのが j
  for(int i=0;i<N;++i){
    for(int j=0;j<N;++j){
      if(c[i]=='-'){ dp[i+1][j]+=dp[i][j]; }
      if(c[i]=='U'){ dp[i+1][j+1]+=dp[i][j],dp[i+1][j]+=dp[i][j]*j; }
      if(c[i]=='D'){ if(0<j){ dp[i+1][j-1]+=dp[i][j]*j*j,dp[i+1][j]+=dp[i][j]*j; } }
    }
  }
  prt(dp[N][0]);
}
accuracy: 0.5348837209302325
time_ms: 20
memory_kb: 49876
final_rank: 20

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; // -2^63 ～ 2^63 = 9 * 10^18（int は -2^31 ～ 2^31 = 2 * 10^9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
const vi DX = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
const vi DY = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004004004004004LL;
double EPS = 1e-16;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), x))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), x))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0; set < (1 << int(d)); ++set) // d ビット全探索（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define smod(n, m) ((((n) % (m)) + (m)) % (m)) // 非負mod
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了

// 汎用関数の定義
template <class T> inline ll pow(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

// 手元環境（Visual Studio）
#ifdef _MSC_VER
#include "local.hpp"
// 提出用（gcc）
#else
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : -1; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : -1; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define gcd __gcd
#define dump(...)
#define dumpel(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) while (1) cout << "OLE"; }
#endif

#endif // 折りたたみ用


////--------------AtCoder 専用--------------
//#include <atcoder/all>
//using namespace atcoder;
//
//using mint = modint1000000007;
////using mint = modint998244353;
////using mint = modint; // mint::set_mod(m);
//
//istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
//ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
//using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;
////----------------------------------------


//【有限体 F_p 上の計算（32 bit）】
template <ll MOD> struct static_modint {
	ll v;

	// コンストラクタ
	static_modint() : v(0) {};
	static_modint(const static_modint& a) = default;
	static_modint(int a) : v(safe_mod(a)) {};
	static_modint(ll a) : v(safe_mod(a)) {};

	// 代入
	static_modint& operator=(const static_modint& a) { v = a.v; return *this; }
	static_modint& operator=(int a) { v = safe_mod(a); return *this; }
	static_modint& operator=(ll a) { v = safe_mod(a); return *this; }

	// 入出力
	friend istream& operator>> (istream& is, static_modint& x) { is >> x.v; x.v = safe_mod(x.v); return is; }
	friend ostream& operator<< (ostream& os, const static_modint& x) { os << x.v; return os; }

	// 非負 mod
	template <class T> static ll safe_mod(T a) { return (((ll)a % MOD) + MOD) % MOD; }

	// 比較
	bool operator==(const static_modint& b) const { return v == b.v; }
	bool operator==(int b) const { return v == safe_mod(b); }
	bool operator==(ll b) const { return v == safe_mod(b); }
	friend bool operator==(int a, const static_modint& b) { return b == a; }
	friend bool operator==(ll a, const static_modint& b) { return b == a; }
	bool operator!=(const static_modint& b) const { return v != b.v; }
	bool operator!=(int b) const { return v != safe_mod(b); }
	bool operator!=(ll b) const { return v != safe_mod(b); }
	friend bool operator!=(int a, const static_modint& b) { return b != a; }
	friend bool operator!=(ll a, const static_modint& b) { return b != a; }

	// 単項演算
	static_modint operator-() const { static_modint a = *this; return a *= -1; }
	static_modint& operator++() { v = safe_mod(v + 1); return *this; }
	static_modint operator++(int) { static_modint tmp = *this; ++(*this); return tmp; }
	static_modint& operator--() { v = safe_mod(v - 1); return *this; }
	static_modint operator--(int) { static_modint tmp = *this; --(*this); return tmp; }

	// 二項演算
	static_modint& operator+=(const static_modint& b) { v = safe_mod(v + b.v); return *this; }
	static_modint& operator-=(const static_modint& b) { v = safe_mod(v - b.v); return *this; }
	static_modint& operator*=(const static_modint& b) { v = safe_mod(v * b.v); return *this; }
	static_modint& operator/=(const static_modint& b) { *this *= b.inv(); return *this; }
	static_modint operator+(const static_modint& b) const { static_modint a = *this; return a += b; }
	static_modint operator-(const static_modint& b) const { static_modint a = *this; return a -= b; }
	static_modint operator*(const static_modint& b) const { static_modint a = *this; return a *= b; }
	static_modint operator/(const static_modint& b) const { static_modint a = *this; return a /= b; }

	// int との演算
	static_modint& operator+=(int b) { v = safe_mod(v + b); return *this; }
	static_modint& operator-=(int b) { v = safe_mod(v - b); return *this; }
	static_modint& operator*=(int b) { v = safe_mod(v * b); return *this; }
	static_modint& operator/=(int b) { *this *= static_modint(b).inv(); return *this; }
	static_modint operator+(int b) const { static_modint a = *this; return a += b; }
	static_modint operator-(int b) const { static_modint a = *this; return a -= b; }
	static_modint operator*(int b) const { static_modint a = *this; return a *= b; }
	static_modint operator/(int b) const { static_modint a = *this; return a /= b; }
	friend static_modint operator+(int a, const static_modint& b) { return b + a; }
	friend static_modint operator-(int a, const static_modint& b) { return -(b - a); }
	friend static_modint operator*(int a, const static_modint& b) { return b * a; }
	friend static_modint operator/(int a, const static_modint& b) { return b.inv() * a; }

	// ll との演算
	static_modint& operator+=(ll b) { v = safe_mod(v + (b % MOD)); return *this; }
	static_modint& operator-=(ll b) { v = safe_mod(v - (b % MOD)); return *this; }
	static_modint& operator*=(ll b) { v = safe_mod(v * (b % MOD)); return *this; }
	static_modint& operator/=(ll b) { *this *= static_modint(b).inv(); return *this; }
	static_modint operator+(ll b) const { static_modint a = *this; return a += b; }
	static_modint operator-(ll b) const { static_modint a = *this; return a -= b; }
	static_modint operator*(ll b) const { static_modint a = *this; return a *= b; }
	static_modint operator/(ll b) const { static_modint a = *this; return a /= b; }
	friend static_modint operator+(ll a, const static_modint& b) { return b + a; }
	friend static_modint operator-(ll a, const static_modint& b) { return -(b - a); }
	friend static_modint operator*(ll a, const static_modint& b) { return b * a; }
	friend static_modint operator/(ll a, const static_modint& b) { return b.inv() * a; }

	// 累乗（0^0 := 1）
	static_modint pow(ll d) const {
		static_modint res(1), pow2 = *this;
		while (d > 0) {
			if (d & 1LL) res *= pow2;
			pow2 *= pow2;
			d /= 2;
		}
		return res;
	}

	// 逆元（0^(-1) は未定義）
	static_modint inv() const {
		Assert(v != 0);
		return pow(MOD - 2);
	}

	// 法の確認
	static int mod() { return MOD; }

	// 値の確認
	int val() const { return int(v); }
};
using mint = static_modint<1000000007>;
//using mint = static_modint<998244353>;
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;


//【階乗など（法が大きな素数）】
/*
* Factorial_mint(int n_max) : O(n_max)
*	n_max! まで計算可能として初期化する．
*
* mint factorial(int n) : O(1)
*	n! を返す．
*
* mint factorial_inv(int n) : O(1)
*	1 / n! を返す．
*
* mint inv(int n) : O(1)
*	1 / n を返す．
*
* mint permutation(int n, int r) : O(1)
*	順列の数 nPr を返す．
*
* mint binomial(int n, int r) : O(1)
*	二項係数 nCr を返す．
*
* mint multinomial(vi rs) : O(|rs|)
*	多項係数 nC[rs] を返す．（n = Σrs）
*/
class Factorial_mint {
	// 階乗，階乗の逆数，逆数の値を保持するテーブル
	int n_max;
	vm fac_, fac_inv_;

public:
	// n! までの階乗とその逆数を前計算しておく．O(n)
	Factorial_mint(int n) : n_max(n), fac_(n + 1), fac_inv_(n + 1) {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		fac_[0] = 1;
		repi(i, 1, n) fac_[i] = fac_[i - 1] * i;

		fac_inv_[n] = fac_[n].inv();
		repir(i, n - 1, 0) fac_inv_[i] = fac_inv_[i + 1] * (i + 1);
	}
	Factorial_mint() : n_max(0) {} // ダミー

	// n! を返す．O(1)
	mint factorial(int n) const {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		Assert(0 <= n && n <= n_max);
		return fac_[n];
	}

	// 1 / n! を返す．O(1)
	mint factorial_inv(int n) const {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		Assert(0 <= n && n <= n_max);
		return fac_inv_[n];
	}

	// 1 / n を返す．O(1)
	mint inv(int n) const {
		// verify : https://atcoder.jp/contests/exawizards2019/tasks/exawizards2019_d

		Assert(0 < n && n <= n_max);
		return fac_[n - 1] * fac_inv_[n];
	}

	// 順列の数 nPr を返す．O(1)
	mint permutation(int n, int r) const {
		Assert(n <= n_max);

		if (r < 0 || n - r < 0) return 0;
		return fac_[n] * fac_inv_[n - r];
	}

	// 二項係数 nCr を返す．O(1)
	mint binomial(int n, int r) const {
		// verify : https://atcoder.jp/contests/abc034/tasks/abc034_c

		Assert(n <= n_max);
		if (r < 0 || n - r < 0) return 0;
		return fac_[n] * fac_inv_[r] * fac_inv_[n - r];
	}

	// 多項係数 nC[r] を返す．O(|r|)
	mint multinomial(const vi& rs) const {
		int n = accumulate(all(rs), 0);
		Assert(n <= n_max);

		mint res = fac_[n];
		repe(r, rs) {
			if (r < 0 || n - r < 0) return 0;
			res *= fac_inv_[r];
		}

		return res;
	}
};


//【上下限の指定された順列の数え上げ】O(n^3)
/*
* [0..n) の順列 p[0..n) のうち，p[0..nu) <= ub[0..nu), p[nu..nu+nl) >= lb[0..nl) (nu + nl = n)
* を満たすものの個数を返す．
* 
* 利用：【階乗など（法が大きな素数）】
*/
mint count_permutations_single_bound(const vi& ub, const vi& lb) {
	int nu = sz(ub), nl = sz(lb), n = nu + nl;

	// ub_cnt[i] : 上界が i であると指定されている p の要素の個数
	vi ub_cnt(n);
	rep(j, nu) {
		if (ub[j] < 0) return 0;
		ub_cnt[min(ub[j], n - 1)]++;
	}

	// lb_cnt[i] : 下界が v であると指定されている p の要素の個数
	vi lb_cnt(n);
	rep(k, nl) {
		if (lb[k] >= n) return 0;
		lb_cnt[max(lb[k], 0)]++;
	}

	Factorial_mint fm(n);

	dump(ub_cnt); dump(lb_cnt);

	// dp_i[j][k] : [0..i) までの数について，
	//	p[0..nu) のいずれかに割り当てることだけが決まっている数が j 個，
	//	p[nu..nu+nl) の中の割り当て待ちの数が k 個ある場合の数
	vvm dp(nu + 1, vm(nl + 1));
	dp[0][0] = 1;

	rep(i, n) {
		vvm dp2(nu + 1, vm(nl + 1));
		repi(j, 0, nu) repi(k, 0, nl - lb_cnt[i]) {
			// 下界が i だと指定されている数が lb_cnt[i] 個あるので，
			// p[nu..nu+nl) の中の割り当て待ちの数がそれだけ増加する．
			dp2[j][k + lb_cnt[i]] += dp[j][k];
		}

		vvm dp3(nu + 1, vm(nl + 1));
		repi(j, 0, nu) repi(k, 0, nl) {
			// i を p[0..nu) のいずれかに割り当てる予約をする場合
			if (j < nu) dp3[j + 1][k] += dp2[j][k];

			// i を p[nu..nu+nl) のいずれかに確定的に割り当てる場合
			if (k > 0) dp3[j][k - 1] += k * dp2[j][k];
		}

		dp = vvm(nu + 1, vm(nl + 1));
		repi(j, ub_cnt[i], nu) repi(k, 0, nl) {
			// p[0..nu) に割り当てることだけが決まっていた未確定の j 個の数のうち，
			// 上界が i だと指定されている ub_cnt[i] 個だけ具体的な数を確定させる．
			dp[j - ub_cnt[i]][k] += dp3[j][k] * fm.permutation(j, ub_cnt[i]);
		}

		dumpel(dp);
	}

	return dp[0][0];
}

	
int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

	int n;
	cin >> n;

	vc c(n);
	cin >> c;

	vc c2;
	repe(x, c) if (x != '-') c2.push_back(x);

	int n2 = sz(c2);
	if (n2 == 0) EXIT(1);

	vi ub, lb;
	rep(i, n2) {
		if (c2[i] == 'U') lb.push_back(i + 1);
		else ub.push_back(i - 1);
	}

	cout << count_permutations_single_bound(ub, lb) << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 3688
final_rank: 6

code_snippet: #pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb(...) emplace_back(__VA_ARGS__)
#define mp(a, b) make_pair(a, b)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, n) for (int i = (int)n - 1; i >= 0; i--)
#define REP(i, l, r) for (int i = l; i < (r); i++)
#define REP2(i, l, r) for (int i = (int)r - 1; i >= (l); i--)
#define siz(x) (ll) x.size()
template <class T>
using rque = priority_queue<T, vector<T>, greater<T>>;

template <class T>
bool chmin(T &a, const T &b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}

template <class T>
bool chmax(T &a, const T &b) {
    if (b > a) {
        a = b;
        return 1;
    }
    return 0;
}

template <class T>
void print(vector<T> a) {
    if (a.empty())
        cout << '\n';
    else {
        for (int i = 0; i < a.size(); i++)
            cout << a[i] << (i + 1 == a.size() ? '\n' : ' ');
    }
}

// __int128_t gcd(__int128_t a, __int128_t b) {
//     if (a == 0)
//         return b;
//     if (b == 0)
//         return a;
//     __int128_t cnt = a % b;
//     while (cnt != 0) {
//         a = b;
//         b = cnt;
//         cnt = a % b;
//     }
//     return b;
// }

long long extGCD(long long a, long long b, long long &x, long long &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long d = extGCD(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

struct UnionFind {
    vector<int> data;
    int num;

    UnionFind(int sz) {
        data.assign(sz, -1);
        num = sz;
    }

    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y)
            return (false);
        if (data[x] > data[y])
            swap(x, y);
        data[x] += data[y];
        data[y] = x;
        num--;
        return (true);
    }

    int find(int k) {
        if (data[k] < 0)
            return (k);
        return (data[k] = find(data[k]));
    }

    int size(int k) {
        return (-data[find(k)]);
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }

    int operator[](int k) {
        return find(k);
    }
};

template <int mod>
struct Mod_Int {
    int x;

    Mod_Int() : x(0) {
    }

    Mod_Int(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {
    }

    static int get_mod() {
        return mod;
    }

    Mod_Int &operator+=(const Mod_Int &p) {
        if ((x += p.x) >= mod)
            x -= mod;
        return *this;
    }

    Mod_Int &operator-=(const Mod_Int &p) {
        if ((x += mod - p.x) >= mod)
            x -= mod;
        return *this;
    }

    Mod_Int &operator*=(const Mod_Int &p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }

    Mod_Int &operator/=(const Mod_Int &p) {
        *this *= p.inverse();
        return *this;
    }

    Mod_Int &operator++() {
        return *this += Mod_Int(1);
    }

    Mod_Int operator++(int) {
        Mod_Int tmp = *this;
        ++*this;
        return tmp;
    }

    Mod_Int &operator--() {
        return *this -= Mod_Int(1);
    }

    Mod_Int operator--(int) {
        Mod_Int tmp = *this;
        --*this;
        return tmp;
    }

    Mod_Int operator-() const {
        return Mod_Int(-x);
    }

    Mod_Int operator+(const Mod_Int &p) const {
        return Mod_Int(*this) += p;
    }

    Mod_Int operator-(const Mod_Int &p) const {
        return Mod_Int(*this) -= p;
    }

    Mod_Int operator*(const Mod_Int &p) const {
        return Mod_Int(*this) *= p;
    }

    Mod_Int operator/(const Mod_Int &p) const {
        return Mod_Int(*this) /= p;
    }

    bool operator==(const Mod_Int &p) const {
        return x == p.x;
    }

    bool operator!=(const Mod_Int &p) const {
        return x != p.x;
    }

    Mod_Int inverse() const {
        assert(*this != Mod_Int(0));
        return pow(mod - 2);
    }

    Mod_Int pow(long long k) const {
        Mod_Int now = *this, ret = 1;
        for (; k > 0; k >>= 1, now *= now) {
            if (k & 1)
                ret *= now;
        }
        return ret;
    }

    friend ostream &operator<<(ostream &os, const Mod_Int &p) {
        return os << p.x;
    }

    friend istream &operator>>(istream &is, Mod_Int &p) {
        long long a;
        is >> a;
        p = Mod_Int<mod>(a);
        return is;
    }
};

ll mpow2(ll x, ll n, ll mod) {
    ll ans = 1;
    x %= mod;
    while (n != 0) {
        if (n & 1)
            ans = ans * x % mod;
        x = x * x % mod;
        n = n >> 1;
    }
    ans %= mod;
    return ans;
}

ll modinv2(ll a, ll mod) {
    ll b = mod, u = 1, v = 0;
    while (b) {
        ll t = a / b;
        a -= t * b;
        swap(a, b);
        u -= t * v;
        swap(u, v);
    }
    u %= mod;
    if (u < 0)
        u += mod;
    return u;
}

ll divide_int(ll a, ll b) {
    return (a >= 0 ? a / b : (a - b + 1) / b);
}

constexpr int mod = 1000000007;
// constexpr int mod = 998244353;
// constexpr int mod = 31607;
using mint = Mod_Int<mod>;

mint mpow(mint x, ll n) {
    bool rev = n < 0;
    n = abs(n);
    mint ans = 1;
    while (n != 0) {
        if (n & 1)
            ans *= x;
        x *= x;
        n = n >> 1;
    }
    return (rev ? ans.inverse() : ans);
}

// ----- library -------
// ----- library -------

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int n;
    cin >> n;
    vector<char> c(n);
    rep(i, n) cin >> c[i];
    vector<int> a;
    rep(i, n) if (c[i] != '-') a.pb(c[i] == 'U');
    n = a.size();
    vector dp(n + 1, vector(n + 1, (mint)0)), ndp(n + 1, vector(n + 1, (mint)0));
    dp[0][0] = 1;
    int cnt = 0;
    rep(t, n) {
        if (!a[t])
            cnt++;
        rep(i, n + 1) rep(j, n + 1) ndp[i][j] = 0;
        REP(i, cnt, n + 1) rep(j, n + 1) {
            rep(f, 2) {
                int ni = i, nj = j;
                mint r = 1;
                if (!f) {
                    r *= i - cnt + 1;
                    ni++;
                } else {
                    r *= j;
                    nj--;
                }
                nj += a[t];
                if (ni > n || nj < 0 || n < nj)
                    continue;
                ndp[ni][nj] += dp[i][j] * r;
            }
        }
        swap(dp, ndp);
    }
    cout << dp[cnt][0] << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 3748
final_rank: 3

code_snippet: #include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <random>
#include <complex>
#include <bitset>
#include <iomanip>
#include <memory>
#include <functional>

#define rep(i, n, s) for (int i = (s); i < int(n); i++)
#define per(i, n, s) for (int i = (n) - 1; i >= int(s); i--)
#define MM << " " <<
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T>
using MaxHeap = std::priority_queue<T>;

using ll = long long;
using Pii = std::pair<int, int>;
using Pll = std::pair<ll, ll>;
using Pdd = std::pair<double, double>;

template <class T>
bool chmin(T &a, const T b) {
    if (b < a) {
        a = b;
        return true;
    } else {
        return false;
    }
}

template <class T>
bool chmax(T &a, const T b) {
    if (a < b) {
        a = b;
        return true;
    } else {
        return false;
    }
}

template <class T>
void vdeb(const std::vector<T> &da) {
    auto n = da.size();
    for (size_t i = 0; i < n; i++) {
        if (i == n - 1)
            std::cout << da[i];
        else
            std::cout << da[i] << " ";
    }
    std::cout << std::endl;
}
template<class T>
void vdeb(const std::vector<std::vector<T>> &da) {
    auto n = da.size();
    for (size_t i = 0; i < n; i++) {
        // std::cout << i << " : ";
        vdeb(da[i]);
    }
    std::cout << std::endl;
}

struct modint {
    long long num;
    const static long long p = 1000000007;
    constexpr static long long pow(long long n, long long k) {//n^k(mod p)
        n %= p;
        long long ret = 1;
        while(k) {
            if(k&1) ret = ret * n % p;
            n = n * n % p;
            k >>= 1;
        }
        return ret;
    }
    // a*A + b*B = 1
    constexpr static void euclid(long long &a, long long &b) { // a>=b A*b+B*(a-a/b*b)=1
        if (a == 1) {
            a = 1;
        }
        else {
            long long A = b, B = a % b;
            euclid(A, B);
            b = (A - (p + a / b) % p * B % p + p) % p;
            a = B;
        }
    }
    constexpr static long long rev(const long long n) {// n*x-p*y=1
        //long long q = p;
        //euclid(p, n, p);
        //return n % q;
        return pow(n,p-2);
    }
    constexpr modint() : num(0) {}
    constexpr modint(long long x) : num(x%p < 0 ? x%p+p : x%p) {}
    constexpr modint inv() const {return rev(num);}
    modint operator-() const {return modint(p-num);}
    modint& operator+=(const modint &other){
        num = (num + other.num) % p;
        return *this;
    }
    modint& operator-=(const modint &other){
        num = (num - other.num + p) % p;
        return *this;
    }
    modint& operator*=(const modint &other){
        num = (num * other.num) % p;
        if(num < 0) num += p;
        return *this;
    }
    modint& operator/=(const modint &other){
        (*this) *= other.inv();
        return *this;
    }
    modint& operator+=(const long long &other){
        num = (num + other) % p;
        return *this;
    }
    modint& operator-=(const long long &other){
        num = (num - other + p) % p;
        return *this;
    }
    modint& operator*=(const long long &other){
        num = (num * other) % p;
        return *this;
    }
    modint& operator/=(const long long &other){
        (*this) *= rev(other);
        return *this;
    }
    modint& operator++(){return *this += 1;}
    modint& operator--(){return *this -= 1;}
    modint& operator=(const long long &other){return (*this) = modint(other);}
    modint operator+(const modint &other) const{return modint(*this) += other;}
    modint operator-(const modint &other) const{return modint(*this) -= other;}
    modint operator*(const modint &other) const{return modint(*this) *= other;}
    modint operator/(const modint &other) const{return modint(*this) /= other;}
    modint operator+(const long long &other) const{return modint(*this) += other;}
    modint operator-(const long long &other) const{return modint(*this) -= other;}
    modint operator*(const long long &other) const{return modint(*this) *= other;}
    modint operator/(const long long &other) const{return modint(*this) /= other;}
    bool operator==(const modint &other) const{return num == other.num;}
};
std::istream& operator>>(std::istream &is, modint x) {
    is >> x.num;
    return is;
}
std::ostream& operator<<(std::ostream &os, const modint &x){
    os << x.num;
    return os;
}

using namespace std;

const int MAX_N = 220;
modint dp[MAX_N][MAX_N][MAX_N];

int main() {
    int n; cin >> n;
    vector<char> da(n);
    rep(i,n,0) cin >> da[i];
    dp[0][0][0] += 1;
    rep(i,n,0) {
        rep(j,n,0) rep(k,n,0) {
            if(da[i] == '-') dp[i+1][j][k] += dp[i][j][k];
            else if(da[i] == 'D') {
                dp[i+1][j][k] += dp[i][j][k] * k;
                if(k > 0 && j > 0) dp[i+1][j-1][k-1] += dp[i][j][k] * k * j;
            } else {
                dp[i+1][j+1][k+1] += dp[i][j][k];
                dp[i+1][j][k] += dp[i][j][k] * j;
            }
        }
    }
    cout << dp[n][0][0] << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 80764
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define all(vec) vec.begin(), vec.end()
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
template <class T>
using V = vector<T>;
template <class T>
inline void chmin(T &a, const T &b) { a = min(a, b); }
template <class T>
inline void chmax(T &a, const T &b) { a = max(a, b); }
template <class T>
inline bool kbit(const T &x, const int &k) { return ((x >> k) & 1LL); }
inline int popcount(const int &n) { return __builtin_popcount(n); }
inline ll popcountll(const ll &n) { return __builtin_popcountll(n); }
inline ll mask(const ll &k) { return (1LL << k) - 1LL; }
template <class T>
void zip(V<T> &v) {
    sort(all(v));
    v.erase(unique(all(v)), v.end());
}
template <class T>
int lwb(V<T> &v, const T &x) { return lower_bound(all(v), x) - v.begin(); }
template <class T>
int upb(V<T> &v, const T &x) { return upper_bound(all(v), x) - v.begin(); }
void dump() {
    cerr << '\n';
}
template <class Head, class... Tail>
void dump(Head &&head, Tail &&...tail) {
    cerr << head << (sizeof...(Tail) == 0 ? " " : ", ");
    dump(std::move(tail)...);
}
template <class T>
void print(const vector<T> &v) {
    for (int i = 0; i < v.size(); i++) cout << v[i] << (i + 1 == v.size() ? '\n' : ' ');
}
template <class T>
void read(vector<T> &v) {
    for (int i = 0; i < v.size(); i++) cin >> v[i];
}
const char sp = ' ', newl = '\n';
const int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
const ll INF = (1LL << 60) - 1LL;
const ll MOD = 1000000007LL;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n;
    cin >> n;
    string s;
    for (int i = 0; i < n; i++) {
        char c;
        cin >> c;
        s.push_back(c);
    }
    V<V<V<ll>>> dp(n + 1, V<V<ll>>(n + 10, V<ll>(n + 10)));
    dp[0][0][0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k <= n; k++) {
                if (s[i] == '-') {
                    (dp[i + 1][j][k] += dp[i][j][k]) %= MOD;
                } else if (s[i] == 'D') {
                    if (j > 0 && k > 0) (dp[i + 1][j - 1][k - 1] += dp[i][j][k] * j * k) %= MOD;
                    (dp[i + 1][j][k] += dp[i][j][k] * j) %= MOD;
                } else if (s[i] == 'U') {
                    (dp[i + 1][j + 1][k + 1] += dp[i][j][k]) %= MOD;
                    (dp[i + 1][j][k] += dp[i][j][k] * k) %= MOD;
                }
            }
        }
    }
    cout << dp[n][0][0] << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 74192
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)

template <int mod>
class Modint {
    static_assert(mod > 0, "Modulus must be positive");

public:
    static constexpr int get_mod() noexcept { return mod; }

    constexpr Modint(long long y = 0) noexcept : x(y >= 0 ? y % mod : (y % mod + mod) % mod) {}

    constexpr int value() const noexcept { return x; }

    constexpr Modint& operator+=(const Modint& p) noexcept { if ((x += p.x) >= mod) x -= mod; return *this; }
    constexpr Modint& operator-=(const Modint& p) noexcept { if ((x += mod - p.x) >= mod) x -= mod; return *this; }
    constexpr Modint& operator*=(const Modint& p) noexcept { x = static_cast<int>(1LL * x * p.x % mod); return *this; }
    constexpr Modint& operator/=(const Modint& p) noexcept { *this *= p.inv(); return *this; }

    constexpr Modint operator-() const noexcept { return Modint(-x); }

    constexpr Modint operator+(const Modint& p) const noexcept { return Modint(*this) += p; }
    constexpr Modint operator-(const Modint& p) const noexcept { return Modint(*this) -= p; }
    constexpr Modint operator*(const Modint& p) const noexcept { return Modint(*this) *= p; }
    constexpr Modint operator/(const Modint& p) const noexcept { return Modint(*this) /= p; }

    constexpr bool operator==(const Modint& p) const noexcept { return x == p.x; }
    constexpr bool operator!=(const Modint& p) const noexcept { return x != p.x; }

    constexpr Modint inv() const noexcept {
        int a = x, b = mod, u = 1, v = 0;
        while (b > 0) {
            int t = a / b;
            std::swap(a -= t * b, b);
            std::swap(u -= t * v, v);
        }
        return Modint(u);
    }

    constexpr Modint pow(long long n) const noexcept {
        Modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend std::ostream& operator<<(std::ostream& os, const Modint& a) {
        return os << a.x;
    }

    friend std::istream& operator>>(std::istream& is, Modint& a) {
        long long t;
        is >> t;
        a = Modint<mod>(t);
        return is;
    }

private:
    int x;
};

using mint = Modint<(int) 1e9 + 7>;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<char> c(n);
    for (auto& x : c) cin >> x;
    vector<vector<mint>> dp(n, vector<mint>(n));
    dp[0][0] = 1;
    rep(i, 0, n) {
        vector<vector<mint>> ndp(n, vector<mint>(n));
        rep(j, 0, n) {
            rep(k, 0, n) {
                if (c[i] == '-') {
                    ndp[j][k] += dp[j][k];
                } else if (c[i] == 'U') {
                    if (j<n-1 && k<n-1) ndp[j+1][k+1] += dp[j][k];
                    ndp[j][k] += dp[j][k] * k;
                } else {
                    ndp[j][k] += dp[j][k] * j;
                    if (j>0 && k>0) ndp[j-1][k-1] += dp[j][k] * j * k;
                }
            }
        }
        dp.swap(ndp);
    }
    cout << dp[0][0] << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 3628
final_rank: 5

code_snippet: #ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
 
#include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
 
#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)
 
// name macro
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T = int>
using VVV = std::vector<std::vector<std::vector<T>>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
using Tp = tuple<ll,ll,ll>;
 
// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
 
// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "No\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}
 
//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}
 
template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif
 
// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
template <class T>
void MUL(std::vector<T> &a, const T x) {
	for(auto &v : a) v *= x;
}
template <class T>
void DIV(std::vector<T> &a, const T x) {
	for(auto &v : a) v /= x;
}
 
// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}

template<typename T>
T ADD(T a, T b){
	T res;
	return __builtin_add_overflow(a, b, &res) ? numeric_limits<T>::max() : res;
}

template<typename T>
T MUL(T a, T b){
	T res;
	return __builtin_mul_overflow(a, b, &res) ? numeric_limits<T>::max() : res;
}

// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
 
// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;

#pragma endregion

using R = long double;
constexpr R EPS=1E-11;

// r の(誤差付きの)符号に従って, -1, 0, 1 を返す.
int sgn(const R& r){ return (r > EPS) - (r < -EPS); }
// a, b の(誤差付きの)大小比較の結果に従って, -1, 0, 1 を返す.
int sgn(const R& a, const R &b){ return sgn(a-b); }
// a > 0 は sgn(a) > 0
// a < b は sgn(a, b) < 0
// a >= b は sgn(a, b) >= 0
// のように書く.
// return s * 10^n

//https://atcoder.jp/contests/abc191/submissions/20028529
long long x10(const string& s, size_t n) {
    if (s.front() == '-') return -x10(s.substr(1), n);
    auto pos = s.find('.');
    if (pos == string::npos) return stoll(s + string(n, '0'));
    return stoll(s.substr(0, pos) + s.substr(pos + 1) + string(n + pos + 1 - s.size(), '0'));
}
 
long long ceildiv(long long a, long long b) {
    if (b < 0) a = -a, b = -b;
    if (a >= 0) return (a + b - 1) / b;
    else return a / b;
}
 
long long floordiv(long long a, long long b) {
    if (b < 0) a = -a, b = -b;
    if (a >= 0) return a / b;
    else return (a - b + 1) / b;
}
 
long long floorsqrt(long long x) {
    assert(x >= 0);
    long long ok = 0;
    long long ng = 1;
    while (ng * ng <= x) ng <<= 1;
    while (ng - ok > 1) {
        long long mid = (ng + ok) >> 1;
        if (mid * mid <= x) ok = mid;
        else ng = mid;
    }
    return ok;
}

inline int topbit(unsigned long long x){
	return x?63-__builtin_clzll(x):-1;
}

inline int popcount(unsigned long long x){
	return __builtin_popcountll(x);
}

inline int parity(unsigned long long x){//popcount%2
	return __builtin_parity(x);
}

const int inf = 1e9;
const ll INF = 1e18;

const ll mod = 1e9 + 7;

void main_() {
	LL(N);
	VEC(char,c,N);
	VVV<ll> dp(N+1,VV<ll>(N+1,V<ll>(N+1)));
	dp[0][0][0] = 1;
	REP(i,N){
	    if(c[i] == '-'){
	        REP(j,N){
	            REP(k,N){
	                dp[i+1][j][k] += dp[i][j][k];
	                dp[i+1][j][k] %= mod;
	            }
	        }
	    }
	    else if(c[i] == 'U'){
	        REP(j,N){
	            REP(k,N){
	                dp[i+1][j][k] += j * dp[i][j][k];
	                dp[i+1][j][k] %= mod;
	                dp[i+1][j+1][k+1] += dp[i][j][k];
	                dp[i+1][j+1][k+1] %= mod;
	            }
	        }
	    }
	    else{
	        REP(j,N){
	            REP(k,N){
	                if(k > 0 && j > 0){
	                    dp[i+1][j-1][k-1] += j * k * dp[i][j][k];
	                    dp[i+1][j-1][k-1] %= mod;
	                    dp[i+1][j][k] += k * dp[i][j][k];
	                    dp[i+1][j][k] %= mod;
	                }
	            }
	        }
	    }
	}
	cout << dp[N][0][0] << endl;
}
 
int main() {
	int t = 1;
	//cin >> t;
	while(t--) main_();
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 68012
final_rank: 15

code_snippet: #pragma GCC target("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
// #include<ext/pb_ds/assoc_container.hpp>
// #include<ext/pb_ds/tree_policy.hpp>
// #include<ext/pb_ds/tag_and_trait.hpp>
// using namespace __gnu_pbds;
// #include<boost/multiprecision/cpp_int.hpp>
// namespace multiprecisioninteger = boost::multiprecision;
// using cint=multiprecisioninteger::cpp_int;
using namespace std;
using ll=long long;
using datas=pair<ll,ll>;
using ddatas=pair<long double,long double>;
using tdata=pair<ll,datas>;
using vec=vector<ll>;
using mat=vector<vec>;
using pvec=vector<datas>;
using pmat=vector<pvec>;
// using llset=tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;
#define For(i,a,b) for(i=a;i<(ll)b;++i)
#define bFor(i,b,a) for(i=b,--i;i>=(ll)a;--i)
#define rep(i,N) For(i,0,N)
#define rep1(i,N) For(i,1,N)
#define brep(i,N) bFor(i,N,0)
#define brep1(i,N) bFor(i,N,1)
#define all(v) (v).begin(),(v).end()
#define allr(v) (v).rbegin(),(v).rend()
#define vsort(v) sort(all(v))
#define vrsort(v) sort(allr(v))
#define uniq(v) vsort(v);(v).erase(unique(all(v)),(v).end())
#define endl "\n"
#define popcount __builtin_popcountll
#define eb emplace_back
#define print(x) cout<<x<<endl
#define printyes print("Yes")
#define printno print("No")
#define printYES print("YES")
#define printNO print("NO")
#define output(v) do{bool f=0;for(auto outi:v){cout<<(f?" ":"")<<outi;f=1;}cout<<endl;}while(0)
#define matoutput(v) do{for(auto outimat:v)output(outimat);}while(0)
constexpr ll mod=1000000007;
// constexpr ll mod=998244353;
constexpr ll inf=1LL<<60;
constexpr long double eps=1e-9;
const long double PI=acosl(-1);
template<class T,class E> ostream& operator<<(ostream& os,const pair<T,E>& p){return os<<"("<<p.first<<","<<p.second<<")";}
template<class T> ostream& operator<<(ostream& os,const vector<T>& v){
  os<<"{";bool f=false;
  for(auto& x:v){if(f)os<<",";os<<x;f=true;}
  os<<"}";
  return os;
}
template<class T> ostream& operator<<(ostream& os,const set<T>& v){
  os<<"{";bool f=false;
  for(auto& x:v){if(f)os<<",";os<<x;f=true;}
  os<<"}";
  return os;
}
template<class T> ostream& operator<<(ostream& os,const multiset<T>& v){
  os<<"{";bool f=false;
  for(auto& x:v){if(f)os<<",";os<<x;f=true;}
  os<<"}";
  return os;
}
template<class T,class E> ostream& operator<<(ostream& os,const map<T,E>& v){
  os<<"{";bool f=false;
  for(auto& x:v){if(f)os<<",";os<<x;f=true;}
  os<<"}";
  return os;
}
template<class T> inline bool chmax(T& a,const T b){bool x=a<b;if(x)a=b;return x;}
template<class T> inline bool chmin(T& a,const T b){bool x=a>b;if(x)a=b;return x;}
#ifdef DEBUG
void debugg(){cout<<endl;}
template<class T,class... Args>void debugg(const T& x,const Args&... args){cout<<" "<<x;debugg(args...);}
#define debug(...) cout<<__LINE__<<" ["<<#__VA_ARGS__<<"]:",debugg(__VA_ARGS__)
#else
#define debug(...) (void(0))
#endif

inline void startupcpp(void) noexcept{
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout<<fixed<<setprecision(15);
}

ll N;
int main(){
  startupcpp();
  cin>>N;
  vector<mat> dp(2,mat(N,vec(N,0)));
  dp[0][0][0]=1;
  ll i,j,k;
  rep(k,N){
    char s;
    cin>>s;
    if(s=='-')continue;
    if(s=='U'){
      rep(i,N)rep(j,N)dp[1][i][j]=dp[0][i][j]*i%mod;
      rep(i,N-1)rep(j,N-1){
        dp[1][i+1][j+1]+=dp[0][i][j];
        if(dp[1][i+1][j+1]>=mod)dp[1][i+1][j+1]-=mod;
      }
    }else{
      rep(i,N)rep(j,N)dp[1][i][j]=dp[0][i][j]*j%mod;
      rep(i,N-1)rep(j,N-1){
        dp[1][i][j]+=dp[0][i+1][j+1]*(i+1)*(j+1)%mod;
        if(dp[1][i][j]>=mod)dp[1][i][j]-=mod;
      }
    }
    swap(dp[0],dp[1]);
  }
  print(dp[0][0][0]);
}
accuracy: 1
time_ms: 10
memory_kb: 4084
final_rank: 2