以下为在HDU上测试的时间,手动取模比%快了不少
dp[i][j]表示长度为i的字符串,最后一个数字为j时的排列种数。
字符为 I 时
如果长的为i-1的字符串都排好了的话,第j位只要找第i-1位的数字比j小的就行
所以就是 dp[i][j]=d[i-1][1]+ d[i-1][2]+ d[i-1][3]+...+d[i-1][j-1]
字符为 D 时
如果长的为i-1的字符串都排好了的话,只要找第i-1位大于等于j的就行
为什么呢,重点来了
你只要把 j~i-1 每个数都 +1 就变成比 j 大的了!!!而且还顺便把j的位置腾出来了!!!十分的巧妙啊!!!
字符为 ?时只要把之前两种情况加起来就行了
最后用前缀和处理一下储存数据就行了。将复杂度降到了N²
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
ll dp[1005][1005];ll sum[1005][1005];
inline int MOD(int x){
if(x >= 0 && x < mod) return x;
return x < 0 ? -MOD(-x) + mod : x - mod;
}
int main()
{
char str[1005];
while(scanf("%s",str) != EOF){
dp[1][1]=1;
sum[1][1]=1;
int len=strlen(str);
for(int i=2;i<=len+1;i++)
for(int j=1;j<=i;j++)
{
if(str[i-2]=='I')
dp[i][j]=MOD(sum[i-1][j-1]);
else if(str[i-2]=='D')
dp[i][j]=MOD(sum[i-1][i-1]-sum[i-1][j-1]+mod);
else
dp[i][j]=sum[i-1][i-1];
sum[i][j]=MOD(sum[i][j-1]+dp[i][j]);
}
printf("%lld\n",sum[len+1][len+1]);
}
return 0;
}