把每个不等关系看做一条边
这样原串就变成一棵树
考虑以i为根的子树,f[i][j]为点i在子树中排名为j的方案数
枚举j,枚举比i小的数中有多少个节点是左儿子
对f数组统计前缀后缀和,乘上组合数转移即可
#include<iostream>
#include<cstdio>
#include<cstring>
#define min(a,b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 105;
typedef long long LL;
const LL mo = 1000000007;
int n,C[N][N],f[N][N],sp[N][N],sf[N][N],siz[N];
char s[N];
inline int Mul(const LL &x,const LL &y) {return x * y % mo;}
inline int Add(const int &x,const int &y) {return x + y < mo ? x + y : x + y - mo;}
inline void Dfs(int x)
{
siz[x] = 1;
int lc = x << 1,rc = x << 1 | 1;
if (lc > n && rc > n) f[x][1] = 1;
else if (lc <= n && rc > n)
{
Dfs(lc); siz[x] += siz[lc];
f[x][s[lc] == '>' ? 2 : 1] = 1;
}
else
{
Dfs(lc); siz[x] += siz[lc];
Dfs(rc); siz[x] += siz[rc];
for (int i = 1; i <= siz[x]; i++)
for (int j = 0; j < min(i,siz[lc] + 1); j++)
{
int k = i - 1 - j;
int tmp = Mul(C[i - 1][j],C[siz[x] - i][siz[lc] - j]);
if (s[lc] == '>') tmp = Mul(tmp,sp[lc][j]);
else tmp = Mul(tmp,sf[lc][j + 1]);
if (s[rc] == '>') tmp = Mul(tmp,sp[rc][k]);
else tmp = Mul(tmp,sf[rc][k + 1]);
f[x][i] = Add(f[x][i],tmp);
}
}
for (int i = n; i; i--) sf[x][i] = Add(sf[x][i + 1],f[x][i]);
for (int i = 1; i <= siz[x]; i++) sp[x][i] = Add(sp[x][i - 1],f[x][i]);
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n; scanf("%s",s + 2); C[0][0] = 1;
for (int i = 1; i <= n; i++)
{
C[i][0] = 1;
for (int j = 1; j <= i; j++)
C[i][j] = Add(C[i - 1][j],C[i - 1][j - 1]);
}
Dfs(1); cout << sf[1][1] << endl;
return 0;
}