题解:dp题。 dp[i][j]表示前1到i的全排列中,最后一位是j的情况。状态转移是:当为‘I’时,dp[i][j] = dp[i - 1][1] +dp[i - 1][2] +...+dp[i -1][j - 1]但是这种情况 可能会出现重复的情况,比如 2,3,1后面会出现2,3,1,2的情况,但这种情况是不符合题意的,所以我们把大于等于j的数全部加1,这样就可以过度到下一个状态了。当为'D'和‘?’时同理。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 1100;
const int mod = 1e9 + 7;
char tt[maxn];
long long dp[maxn][maxn];
long long num[maxn][maxn];
int main()
{
while (~scanf("%s", tt + 1))
{
int len = strlen(tt + 1) + 1;
memset(dp, 0, sizeof(dp));
// num[1][1] = 1;
memset(num, 0, sizeof(num));
num[0][0] = 1;
num[1][1] = 1;
for (int i = 2; i <= len; i ++)
{
for (int j = 1; j <= i; j ++)
{
if (tt[i - 1] == 'I')
{
dp[i][j] = num[i - 1][j - 1] % mod;
}
else if (tt[i - 1] == 'D')
{
dp[i][j] = (num[i - 1][i - 1] - num[i - 1][j - 1] + mod) % mod;
}
else
dp[i][j] = num[i - 1][i - 1] % mod;
num[i][j] = (num[i][j - 1] + dp[i][j]) % mod;
}
}
printf("%lld\n", num[len][len]);
}
}