题意:
给你一个长度为n的指定的升降序列,问有多少种排列,符合这样的序列。
题解:
训练赛的时候没想出来,大概这种排列的dp需要转换一下思维吧。
考虑dp[i][j]表示前i个数只用1~i,结尾为j。
然后就有
如果s[i - 1]是' I ',那么dp[i][j] = dp[i-1][j-1] + dp[i-1][j-2] + .. + dp[i-1][1]。
如果s[i - 1]是‘D’,那么dp[i][j] = dp[i-1][j] + dp[i-1][j+1] + ... + dp[i-1][i]。
如果s[i - 1]是‘?’,那么dp[i][j] = dp[i-1][i-1] + ... + dp[i-1][1]。
比较巧妙。需要好好想想,详细题解:传送门
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 #define mst(a,b) memset(a,b,sizeof(a)) 5 6 const int N=1007,P=1e9+7; 7 char s[N]; 8 int dp[2][N],n,x; 9 10 void up(int &a,int b){a+=b;if(a>=P)a-=P;} 11 12 int main(){ 13 while(~scanf("%s",s+1)) 14 { 15 n=strlen(s+1)+1; 16 mst(dp,0),dp[x=0][1]=1; 17 F(i,2,n) 18 { 19 x^=1,mst(dp[x],0); 20 if(s[i-1]=='?') 21 { 22 F(j,1,i-1)up(dp[x][1],dp[x^1][j]); 23 F(j,2,i)up(dp[x][j],dp[x][1]); 24 } 25 else if(s[i-1]=='I') 26 { 27 F(j,1,i)up(dp[x][j],dp[x][j-1]+dp[x^1][j-1]); 28 } 29 else 30 { 31 for(int j=i;j;j--) 32 up(dp[x][j],dp[x][j+1]+dp[x^1][j]); 33 } 34 } 35 int ans=0; 36 F(i,1,n)up(ans,dp[x][i]); 37 printf("%d ",ans); 38 } 39 return 0; 40 }