Number String
64-bit integer IO format: %I64d Java class name: Main
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.
Input
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'.
Output
Sample Input
II ID DI DD ?D ??
Sample Output
1 2 2 1 3 6
Source
题目分析:对于一个n个数排列,用I 表示后一个数比前一个数大, 用D表示后一个数比前一个数小。例如:123 就是II 。312就是DI。?表示可以I 或者D。给I,D,?组成的程度为n的序列,找出这个序列所能表示的全排列的个数,每个数字只能出现一次。
显然如果序列的长度为n , 则为1 ~ n+1的排列。
设dp[ i ][ j ] 为 前i - 1 已经排列好 , 第i 位为j的排列数。sigma dp[ n + 1 ][ j ] , j 从1 到n+1 ,为要求的结果。
如果第i位对应 ‘ I ’ ,则dp[ i ][ j ] = dp[ i - 1][ j - 1] + dp[ i - 1][ j - 2] + …… + dp[ i - 1 ][ 1 ] ;
考虑第i位时,前面i - 1 位都已经排好,且第i - 1位的数字 小于 j 的排列都可以在第i位放j , 所以可得上式。
如果第j位对应‘D’ , 则dp[ i ][ j ] = dp[ i - 1][ i - 1] + dp[ i - 1][ i - 2 ] + …… + dp[ i - 1 ][ j ] ;
对于第 i - 1 位的数字大于等于 j 的排列 , 将前 i - 1 位中大于等于j的数字都加1 ,前面的情况依然成立 , 且第 i 位可以放 j 。
例如 (1 ,3 , 2) 。第4位对应D , 想放2 。将前三位大于等于2的加1,得到 (1 , 4, 3 )。将2放在后面,得到(1,4,3,2)。 所以第i - 1 位大于等于 j 的都可以入选 , 因为加1之后 , 肯定比 j 大。
如果第i为对应‘?’ , 则以上两种情况相加。
用sum[ i ][ j ] 表示 dp[ i ][ j ] + dp[ i ][ j - 1 ] + …… + dp[ i ][ 1 ]
则,状态转移可写成:
对应 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 ][ i - 1]
以上内容摘自玻璃年华Alex
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int mod = 1000000007; 5 const int maxn = 1010; 6 LL dp[maxn][maxn],sum[maxn][maxn]; 7 char str[maxn]; 8 int main(){ 9 while(~scanf("%s",str)){ 10 int n = strlen(str)+1; 11 dp[1][1] = sum[1][1] = 1; 12 for(int i = 2; i <= n; ++i){ 13 for(int j = 1; j <= i; ++j){ 14 if(str[i - 2] == 'I') dp[i][j] = sum[i - 1][j - 1]; 15 else if(str[i - 2] == 'D') dp[i][j] = (sum[i-1][i-1] - sum[i-1][j-1] + mod)%mod; 16 else dp[i][j] = sum[i-1][i-1]; 17 sum[i][j] = (sum[i][j-1] + dp[i][j])%mod; 18 } 19 } 20 printf("%I64d ",sum[n][n]); 21 } 22 return 0; 23 }