zoukankan      html  css  js  c++  java
  • 合法括号匹配[简单的序列,合法括号匹配]

    dp

    简单的序列

    题解

    A过一遍,再做时却错了

    真是具有讽刺意味

    合法括号匹配

    题意

    每次可以在末尾加(,),或删除最末位,(长度为0时也可进行删除操作)

    问最后合法方案数(长度任意)

    题解

    设$g[i][j]$表示进行i次操作,最终长度为j方案数

    最终答案就是$sumlimits_{i=0}^{i<=n}g[n][i]*catalan()$

    模数可能不是质数$n^2$推一下catalan

    然而$g$我推挂了

    因为我们要求的是长度为j方案,直接的想法是将(,)等效,

    $g[i][j]=g[i-1][j-1]+g[i-1][j+1]$

    但实际上(,)在删除时是不等效的$[添加时仍是等效的!]$

    ((删除最末位,()删除最末位最终得到都是(

    但这么算就算少了,

    $g[i][j]=g[i-1][j-1]+g[i-1][j+1]*2$

    这才是这个题要点

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define A 5101
    ll f[A][A],g[A][A];
    ll n,mod;
    int main(){
    //    freopen("da.in","r",stdin);
    //    freopen("ans.bf","w",stdout);
        scanf("%lld%lld",&n,&mod);
        f[0][0]=1;
        for(ll i=1;i<=n;i++)
            for(ll j=0;j<=i;j++){
                if(j!=0)
                    f[i][j]=(f[i-1][j-1]+f[i-1][j+1])%mod;
                else 
                    f[i][j]=f[i-1][j+1];
            }
        g[0][0]=1;
        for(ll i=1;i<=n;i++)
            for(ll j=0;j<=i;j++){
                if(j==0)//j==0
                    g[i][j]=(g[i-1][j]+g[i-1][j+1]*2)%mod;
                else 
                    g[i][j]=(g[i-1][j-1]+g[i-1][j+1]*2)%mod;
            }
        ll ans=0;
        for(ll i=0;i<=n;i++){
    //        printf("f[%lld][0]=%lld g[%lld][%lld]=%lld
    ",i,f[i][0],n,i,g[n][i]);
            ans=(ans+f[i][0]*g[n][i])%mod;
        }
        printf("%lld
    ",ans);
    }
    View Code
  • 相关阅读:
    C语言中 单引号与双引号的区别
    Linux主分区,扩展分区,逻辑分区的联系和区别
    fdisk
    df du 的区别
    filesystem
    git clone
    curl
    HDR 高动态范围图像
    source ~/.bashrc 什么意思
    linux 挂载
  • 原文地址:https://www.cnblogs.com/znsbc-13/p/11677698.html
Copyright © 2011-2022 走看看