• hdu4055


    hdu4055

    题意

    给出一个长度为 n - 1 的字符串,要求构造一个包含数字 [1, n] 的排列,从第二位开始,'I' 表示当前位数字比前一位大,'D' 表示当前位数字比前一位小,'?' 表示可大可小。问有多少满足条件的 n 的排列。

    分析

    设 dp[i][j] 为 [1, i] 已排列好,最后一位为 j 的方案数。
    如果 s[i] = 'I', (dp[i][j] = sum_{k=1}^{j-1}{dp[i-1][k]});
    如果 s[i] = 'D', (dp[i][j] = sum_{k=j}^{i-1}{dp[i-1][k]});
    我们可以假定每次使第 i 位为 j 时,前面 >= j 的值都加 1 了,保证仍是一个完整的排列。
    注意到我们主要用到的是 dp[i-1][k] 的累加和,可以让 sum[i - 1][k] 表示 (sum_{x=1}^{k}dp[i-1][x]) 的和。
    前缀和快速求解。sum数组可以改用滚动数组实现。

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN = 5005;
    const int MOD = 1e9 + 7;
    int dp[MAXN][MAXN];
    int sum[MAXN][MAXN];
    char s[MAXN];
    int main() {
        while(~scanf("%s", s)) {
            int l = strlen(s);
            sum[1][1] = 1;
            for(int i = 2; i < l + 2; i++) {
                for(int j = 1; j <= i; j++) {
                    if(s[i - 2] == 'I') {
                        dp[i][j] = sum[i - 1][j - 1];
                    } else if(s[i - 2] == 'D') {
                        dp[i][j] = (sum[i - 1][i - 1] - sum[i - 1][j - 1] + MOD) % MOD;
                    } else {
                        dp[i][j] = sum[i - 1][i - 1];
                    }
                    sum[i][j] = (sum[i][j - 1] + dp[i][j]) % MOD;
                }
            }
            printf("%d
    ", sum[l + 1][l + 1]);
        }
        return 0;
    }
    
  • 相关阅读:
    php单例设计模式
    js实用技巧
    快速排序java实现
    PHP大小写问题
    http转https
    wx-charts 微信小程序图表插件
    如何判断微信内置浏览器 MicroMessenger
    小程序:下拉加载更多时bindscrolltolower多次执行
    PHP内核
    CSS的4种引入方式以及优先级
  • 原文地址:https://www.cnblogs.com/ftae/p/7057372.html
Copyright © 2020-2023  润新知