HDU - 4055 Number String
题目大意:给定一个字符串,I表示本字符要比前一个字符大,D表示本字符要不前一个字符小,?可大可小,问1~n的所有排列中,有多少满足条件
具体思路:DP
f[i][j]表示i个数的排列,第i个是j的方案数
如果是I,f[i][j]=f[i-1][1]+...+f[i-1][j-1]
如果是D,f[i][j]=f[i-1][i-1]+...+f[i-1][1]
然后加个前缀和优化就好了
AC代码
#include<bits/stdc++.h> #define int long long using namespace std; const int ha=1000000007; char s[10000]; int n,m,i,j,f[1010][1010],k,sum[1010][1010],ans; main() { while(~scanf("%s",s)) { n=strlen(s)+1; memset(f,0,sizeof(f)); memset(sum,0,sizeof(sum)); f[1][1]=1; for (i=1; i<=n; i++)sum[1][i]=1; for (i=2; i<=n; i++) { for (j=1; j<=i; j++) { if(s[i-2]=='D')f[i][j]=sum[i-1][i-1]-sum[i-1][j-1]+ha;else if(s[i-2]=='I') f[i][j]=sum[i-1][j-1]-sum[i-1][0]+ha;else f[i][j]=sum[i-1][i-1]-sum[i-1][0]+ha; sum[i][j]=f[i][j]%ha; } for (j=1;j<=n;j++)sum[i][j]+=sum[i][j-1],sum[i][j]%=ha; } ans=0; for (i=1; i<=n; i++)ans+=f[n][i]; printf("%lld\n",ans%ha); } return 0; }