题解
可以设
f
i
,
j
f_{i,j}
fi,j表示用一个1到i的排列,且满足题目给出序列的前i-1项,最后一项为j的方案数,
考虑如何转移,枚举当前位置填的数是k,为了使得之前的i-1的全排列变为一个i的全排列,可以让原来排列里面所有大于等于k的数都+1,这样就可以变成i的排列,而且还知道最后一个位置。
维护一个前缀和就可以n方解决。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define G getchar
using namespace std;
const int mo=1000000007;
char ch,s[1003];
int n,f[1003][1003],sum,ans;
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int main()
{
for(ch=G();ch!='I' && ch!='D' && ch!='?';ch=G());
for(n=1;ch=='I' || ch=='D' || ch=='?';ch=G())s[++n]=ch;
f[1][1]=1;
for(int i=2;i<=n;i++)
{
sum=0;
if(s[i]=='I')
{
for(int j=1;j<i;j++)
sum=add(sum,f[i-1][j]),f[i][j+1]=sum;
}
else if(s[i]=='D')
{
for(int j=i-1;j;j--)
sum=add(sum,f[i-1][j]),f[i][j]=sum;
}
else
{
for(int j=1;j<i;j++)sum=add(sum,f[i-1][j]);
for(int j=1;j<=i;j++)f[i][j]=sum;
}
}
ans=0;
for(int i=1;i<=n;i++)ans=add(ans,f[n][i]);
printf("%d",ans);
return 0;
}