The signature of a permutation is a string that is computed as follows: for each pair of consecutive elements of the permutation, write down the letter 'I' (increasing) if the second element is greater than the first one, otherwise write down the letter 'D' (decreasing). For example, the signature of the permutation {3,1,2,7,4,6,5} is "DIIDID".
Your task is as follows: You are given a string describing the signature of many possible permutations, find out how many permutations satisfy this signature.
Note: For any positive integer n, a permutation of n elements is a sequence of length n that contains each of the integers 1 through n exactly once.
Each test case consists of a string of 1 to 1000 characters long, containing only the letters 'I', 'D' or '?', representing a permutation signature.
Each test case occupies exactly one single line, without leading or trailing spaces.
Proceed to the end of file. The '?' in these strings can be either 'I' or 'D'.
For each test case, print the number of permutations satisfying the signature on a single line. In case the result is too large, print the remainder modulo 1000000007.
II ID DI DD ?D ??
1 2 2 1 3 6
Permutation {1,2,3} has signature "II".
Permutations {1,3,2} and {2,3,1} have signature "ID".
Permutations {3,1,2} and {2,1,3} have signature "DI".
Permutation {3,2,1} has signature "DD".
"?D" can be either "ID" or "DD".
"??" gives all possible permutations of length 3.
题意:给出一个长度为len的字符串,I表示上升,D表示下降,求出长度为len+1数字范围在1~len+1满足字符串所描述情况的序列个数
思路:
①dp[i][j]表示长度为i,数字j结尾的情况
②同时这道题关键要理解一点,假设现有长度为5的序列1 3 5 4 2,若要在第6个位置添加1~6,假设添加的是i,则把大于等于i的数都+1,这样前5个数的序列情况保持不变,例如添加3,序列变成1 4 6 5 2 3,这样1 4 6 5 2 和 1 3 5 4 2上升下降情况是一样的。
③I的情况:假设要求dp[6][4],即长度为6,第6位为4的序列个数,肯定是把长度为5末位为1 2 3的序列的第6位添加4,构成后两位为1 4,2 4,3 4的上升序列,即dp[6][4]=dp[5][1]+dp[5][2]+dp[5][3],相当于运用②的性质把4从里面提取到最后
④D的情况:假设要求dp[6][4],就与上升的情况相反,在6 5 后添加4构成下降序列,这里与上升的情况有一点区别,因为这里dp[6][4]=dp[5][4]+dp[5][5],这里长度为5数字范围肯定只有在1~5以内,而运用②的性质,就会把结尾dp[5][4]的情况考虑进去,使得其变成5 4的情况,而dp[5][5]会变成6 4的情况
⑤?的情况:即是把I的情况加上D的情况,相当于dp[6][4]=dp[5][1]+dp[5][2]……+dp[5][5]
⑥用上面的情况相当于O(n^3)的解法,只要用sum[i][j]记录每一层,dp[i][1]加到dp[i][j]的和,I的情况就变成dp[i][j]=sum[i-1][j-1],D的情况就变成dp[i][j]=sum[i-1][i-1]-sum[i-1][j-1],?的情况就变成dp[i][j]=sum[i-1][j-1],以此降为O(n^2)的复杂度
#include
#include
#define LL long long
#define MOD 1000000007
char str[1010];
LL dp[1005][1005],sum[1005][1005];
int main(void){
while(~scanf("%s",str+2)){
memset(sum,0,sizeof(sum));
dp[1][1]=sum[1][1]=1;
int len=strlen(str+2)+1;
for(int i=2;i<=len;i++){
for(int j=1;j<=i;j++){
if(str[i]=='I')
dp[i][j]=sum[i-1][j-1];
else if(str[i]=='D')
dp[i][j]=sum[i-1][i-1]-sum[i-1][j-1];
else dp[i][j]=sum[i-1][i-1];
sum[i][j]=(sum[i][j-1]+dp[i][j])%MOD;
}
}
printf("%lld\n",(sum[len][len]%MOD+MOD)%MOD);
}
return 0;
}