HDU 4055 Number String 计数DP

Number String HDU - 4055

定义一个只含 1n1\sim n 的数字串 {a1,a2,,an}\{a_1,a_2,\cdots,a_n\} 的签名如下,假如当前大于前一位,则当前位记为 II,否则记为 DD,比如:

the signature of the permutation {3,1,2,7,4,6,5} is “DIIDID”.

现在给一个长度为 nn 的签名,问符合该签名的数字串有多少个?

dp[i][j]dp[i][j] 表示前 ii 个数,末尾是 jj 对应的个数,按情况讨论(令 s[i][j]=k=1jdp[i][k]s[i][j]=\sum_{k=1}^jdp[i][k]):

(1)a[i]=?a[i]='?'

dp[i][j]=k=1i1dp[i1][k]=s[i1][i1] dp[i][j]=\sum_{k=1}^{i-1}dp[i-1][k]=s[i-1][i-1]

(2)a[i]=Ia[i]='I'

dp[i][j]=k=1j1dp[i1][k]=s[i1][j1] dp[i][j]=\sum_{k=1}^{j-1}dp[i-1][k]=s[i-1][j-1]

(3)a[i]=Da[i]='D'

dp[i][j]=k=ji1dp[i1][k]=s[i1][i1]s[i1][j1] dp[i][j]=\sum_{k=j}^{i-1}dp[i-1][k]=s[i-1][i-1]-s[i-1][j-1]

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 1010
#define MOD 1000000007
using namespace std;
typedef long long ll;
char a[MAXN];
ll dp[MAXN][MAXN],s[MAXN][MAXN];
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    while(scanf(" %s ",a)!=EOF){
        int n=strlen(a)+1;
        dp[1][1]=s[1][1]=1;
        for(int i=2;i<=n;i++){
            char c=a[i-2];
            for(int j=1;j<=n;j++){
                if(c=='?')
                    dp[i][j]=s[i-1][i-1];
                else if(c=='I')
                    dp[i][j]=s[i-1][j-1];
                else dp[i][j]=(s[i-1][i-1]-s[i-1][j-1]+MOD)%MOD;
                s[i][j]=(s[i][j-1]+dp[i][j])%MOD;
            }
        }
        printf("%lld\n",s[n][n]);
    }
    return 0;
}

在这里插入图片描述

posted @ 2020-03-29 18:53  winechord  阅读(74)  评论(0编辑  收藏  举报