zoukankan      html  css  js  c++  java
  • Codeforces

    http://codeforces.com/problemset/problem/909/C

    好像以前做过,但是当时没做出来,看了题解也不太懂。

    一开始以为只有上面的for有了循环体,这里的statement就可以随便放,但其实并不是这样,statement的位置会取消比它缩进更多或相等的for的可append性。所以设计dp顺序的时候要用dp[i][j]表示第i行剩余可选for循环数量为j的选法数。那么递推公式也不难(才怪),看看代码就好了。

    有几个可以优化的,一个是滚动数组,另一个是线性求前缀和然后均摊O(1)减少一个维度的时间复杂度。

    注意读入%c之前要加一个空格来过滤前面还保留在流中的换行符

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    ll dp[5005][5005];
    char ch[5005];
    int n;
    int p=1000000007;
    
    int main(){
        scanf("%d",&n);
    
        for(int i=0;i<n;i++){
            scanf(" %c",&ch[i]);
            //printf("%c
    ",ch[i]);
        }
    
        int cntf=0;
        if(ch[0]=='f')
            cntf++;
        dp[0][cntf]=1;
        //可跟随的f的数量
        /*for(int j=0;j<=cntf;j++){
            printf("dp[%d][%d]=%lld
    ",0,j,dp[0][j]);
        }
        printf("
    ");*/
    
    
        for(int i=1;i<n;i++){
            if(ch[i]=='f'){
                cntf++;
                if(i-1>=0&&ch[i-1]=='f'){
                    //dp[i]=dp[i-1];
                    //不得不跟随
                    for(int j=1;j<=cntf;j++){
                        dp[i][j]=dp[i-1][j-1];
                    }
                }
                else if(i-1>=0&&ch[i-1]=='s'){
                    //任选一个f进行跟随
                    ll sum=0;
                    for(int j=0;j<=cntf-1;j++){
                        sum=(sum+dp[i-1][j])%p;
                    }
    
                    ll presum=0;
                    for(int j=1;j<=cntf;j++){
                        dp[i][j]=(sum-presum+p)%p;
                        presum=(presum+dp[i-1][j-1])%p;
                    }
                }
            }
            else{
                if(i-1>=0&&ch[i-1]=='f'){
                    //dp[i]=dp[i-1];
                    //不得不跟随
                    for(int j=0;j<=cntf;j++){
                        dp[i][j]=dp[i-1][j];
                    }
                }
                else if(i-1>=0&&ch[i-1]=='s'){
                    //任选一个f进行跟随
                    ll sum=0;
                    for(int j=0;j<=cntf;j++){
                        sum=(sum+dp[i-1][j])%p;
                    }
    
                    ll presum=0;
                    for(int j=0;j<=cntf;j++){
                        dp[i][j]=(sum-presum+p)%p;
                        presum=(presum+dp[i-1][j])%p;
                    }
                }
            }
            /*for(int j=0;j<=cntf;j++){
                printf("dp[%d][%d]=%lld
    ",i,j,dp[i][j]);
            }
            printf("
    ");*/
        }
    
        ll sum=0;
        for(int j=0;j<=cntf;j++){
            sum=(sum+dp[n-1][j])%p;
        }
        printf("%lld
    ",sum);
    
    }

    ---恢复内容结束---

  • 相关阅读:
    【转】23种设计模式详解
    JavaScript 中的对象引用
    iOS网络请求之NSURLSession
    学习编程是否做笔记的思考
    汇编语言——统计一个字符串中的大写字母、小写字母、数字和其他字符的个数,并显示
    windows7 64位如何调出debug
    Code:Blocks编写后出现如下错误
    iOS中Git的使用
    任意定义一个二维数组,实现矩阵的转置——java
    将八进制数转换为十进制数——java
  • 原文地址:https://www.cnblogs.com/Yinku/p/10327682.html
Copyright © 2011-2022 走看看