• 陨石的秘密


    陨石的秘密

    分别给出(l_1,l_2,l_3)({},[],()),优先级从低到高,组成一个合法的括号序列,并保证一个括号里的括号优先级要大于等于它,定义深度为括号里套括号的层数,问深度恰好为d的方案数(mod 11380)(0 <= L1 <= 10,0 <= L2 <= 10,0 <= L3 <= 10,0 <= D <= 30)

    不能单独去考虑一个括号,递推状态无法表现,于是考虑划分一个序列成为几个合法序列的方案数,但是注意到可能会有重复,于是用一个括号强制包一个序列即可,现在问题在于枚举深度太麻烦了,于是考虑差分设状态,因此可以设出(f[i][j][k][l])表示深度小于等于i,有j个({})k个([])l个(())的方案数,因此不难有

    [f[i][j][k][l]=egin{cases}1& if(j==k==l==0)\sum_{p=1}^jsum_{q=0}^ksum_{r=0}^lf[i-1][p-1][q][r] imes f[i][j-p][k-q][l-r]+&else\ sum_{p=1}^ksum_{q=0}^lf[i-1][0][p-1][q] imes f[i][j][k-q][l-q]+sum_{p=1}^l\f[i-1][0][0][p-1] imes f[i][j][k][l-p]end{cases}]

    边界:(f[i][0][0][0]=1,i=0,1,2,..,d)

    答案:(f[d][l1][l2][l3]-f[d-1][l1][l2][l3])

    参考代码:

    阶段实现:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define lzq 11380
    using namespace std;
    int dp[11][11][11][31];
    int main(){
        int l1,l2,l3,d;
        scanf("%d%d%d%d",&l1,&l2,&l3,&d);
        for(int i(0);i<=d;++i)dp[0][0][0][i]=1;
        for(int i(1),j,k,l,p,q,r;i<=d;++i)
            for(j=0;j<=l1;++j)
                for(k=0;k<=l2;++k)
                    for(l=0;l<=l3;++l){
                        for(p=1;p<=j;++p)
                            for(q=0;q<=k;++q)
                                for(r=0;r<=l;++r)
                                    dp[j][k][l][i]+=dp[p-1][q][r][i-1]*
                                        dp[j-p][k-q][l-r][i]%lzq;
                        for(p=1;p<=k;++p)
                            for(q=0;q<=l;++q)
                                dp[j][k][l][i]+=dp[0][p-1][q][i-1]*
                                    dp[j][k-p][l-q][i]%lzq;
                        for(p=1;p<=l;++p)
                            dp[j][k][l][i]+=dp[0][0][p-1][i-1]*
                                dp[j][k][l-p][i];
                        dp[j][k][l][i]%=lzq;
                    }
        int ans(dp[l1][l2][l3][d]);
        if(d)ans-=dp[l1][l2][l3][d-1];
        (ans+=lzq)%=lzq;printf("%d",ans);
        return 0;
    }
    

    dfs实现:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define lzq 11380
    using namespace std;
    bool is[31][11][11][11];
    int dp[31][11][11][11];
    int dfs(int,int,int,int);
    il int mod(int);
    int main(){
        int l1,l2,l3,D;
        scanf("%d%d%d%d",&l1,&l2,&l3,&D);
        for(int i(0);i<=D;++i)dp[i][0][0][0]|=true;
        printf("%d",mod(dfs(D,l1,l2,l3)-dfs(D-1,l1,l2,l3)));
        return 0;
    }
    il int mod(int x){
        return ((x%=lzq)+=lzq)%=lzq;
    }
    int dfs(int a,int b,int c,int d){
        if(a<0||b<0||c<0||d<0)return 0;
        if(is[a][b][c][d])return dp[a][b][c][d];
        int &x(dp[a][b][c][d]),i,j,k;
        for(i=1;i<=b;++i)
            for(j=0;j<=c;++j)
                for(k=0;k<=d;++k)
                    x+=dfs(a-1,i-1,j,k)*dfs(a,b-i,c-j,d-k)%lzq;
        for(i=1;i<=c;++i)
            for(j=0;j<=d;++j)
                x+=dfs(a-1,0,i-1,j)*dfs(a,b,c-i,d-j)%lzq;
        for(i=1;i<=d;++i)
            x+=dfs(a-1,0,0,i-1)*dfs(a,b,c,d-i)%lzq;
        return is[a][b][c][d]|=true,x%=lzq;
    }
    
  • 相关阅读:
    BZOJ 1014 火星人prefix
    BZOJ 1013 球形空间产生器
    BZOJ 1012 最大数
    BZOJ 1011 遥远的行星
    BZOJ 1010 玩具装箱
    BZOJ 1009 GT考试
    BZOJ 1008 越狱
    BZOJ 1007 水平可见直线
    BZOJ 1006 神奇的国度
    Luogu 1450 [HAOI2008]硬币购物
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10995850.html
Copyright © 2020-2023  润新知