zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    yarn的安装和使用
    git clone不了项目文件的解决方法和----vscode操作git的方法
    vue使用swiper遇到的坑
    stylus介绍与引入
    Win10在当前目录快速打开cmd的方法
    git切换到指定分支,git新建分支与合并
    jQuery之表格隔行变色
    jQuery之onload与ready
    jQuery之多库共存
    jQuery之插件
  • 原文地址:https://www.cnblogs.com/ftae/p/7057372.html
Copyright © 2011-2022 走看看