• B(升降序列)


    B(升降序列)

    pic


    题目

    【题目描述】

    对于一个排列,考虑相邻的两个元素,如果后面一个比前面一个大,表示这个位置是上升的,用 I 表示,反之这个位置是下降的,用 D 表示。如排列 3,1,2,7,4,6,5 可以表示为 DIIDID。

    现在给出一个长度为 n-1 的排列表示,问有多少种 1 到 n 的排列满足这种表示。

    【输入输出格式】

    输入格式:
    一个字符串 S,S 由 I,D,?组成。?表示这个位置既可以为 I,又可以为 D。

    输出格式:
    有多少种排列满足上述字符串。输出排列数模 1000000007。

    【输入输出样例】

    输入样例#1:
    ?D
    输出样例#1:
    3
    【说明】
    对于 20%的数据,S 长度 ≤ 10;
    对于 100%的数据,S 长度 ≤ 1000。

    思路

    dp。
    (dp[i][j])表示i这么长的序列,最后一个是j的符合要求的序列个数
    于是有方程:

    [dp_{i,j}= egin{cases} sum_{k=1}^{j-1} dp_{i-1,k} ext{Order='I'} \[1ex] \ sum_{k=j}^{i-1} dp_{i-1,k} ext{Order='D'}end{cases} ]

    为了简化计算,计算(dp_{i,...})之前,把(dp_{i-1,...})处理成前缀和的形式。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define mod 1000000007
    #define LL long long
    #define File freopen("B.in","r",stdin);freopen("B.out","w",stdout)
    using namespace std;
    const int maxn=1000+5;
    
    LL n=1,dp[maxn][maxn],ans;
    char c;
    
    int main() {
        ios::sync_with_stdio(false);
    //    File;
        c=getchar();
        dp[1][1]=1;
        while(c=='?' || c=='D' || c=='I') {
            n++;
            for(LL i=1; i<n; ++i) {
                dp[n-1][i]=(dp[n-1][i]+dp[n-1][i-1])%mod;
            }
            if(c=='I') {
                for(LL i=2; i<=n; ++i)
                    dp[n][i]=dp[n-1][i-1]%mod;
            }
            if(c=='D') {
                for(LL i=1; i<n; ++i) {
                    dp[n][i]=(dp[n-1][n-1]-dp[n-1][i-1]+mod)%mod;
                }
            }
            if(c=='?') {
                for(LL i=2; i<=n; ++i) {
                    dp[n][i]=dp[n-1][i-1]%mod;
                }
                for(LL i=1; i<n; ++i) {
                    dp[n][i]+=(dp[n-1][n-1]-dp[n-1][i-1]+mod)%mod;
                }
            }
            c=getchar();
        }
        ans=0;
        for(LL i=1; i<=n; ++i) {
            ans+=dp[n][i];
            ans=ans%mod;
        }
        cout<<ans%mod;
        return 0;
    }
    
    
  • 相关阅读:
    Leetcode 1002. 查找常用字符
    Leetcode 1020. 将数组分成和相等的三个部分
    Leetcode 1021. 最佳观光组合
    Leetcode 1022. 可被 K 整除的最小整数
    算法入门经典第六章 例题6-9 天平
    例题6-7 树的层次遍历
    算法入门经典第六章 例题6-4 破损的键盘
    算法入门经典-第五章 例题5-7 丑数
    算法入门经典第六章 例题6-5 移动盒子
    算法入门经典第六章 例题6-2 铁轨
  • 原文地址:https://www.cnblogs.com/YQAccelerator/p/7413783.html
Copyright © 2020-2023  润新知