• BZOJ 4824 [Cqoi2017]老C的键盘 ——树形DP


    每一个限制条件相当于一条有向边,

    忽略边的方向,就成了一道裸的树形DP题

    同BZOJ3167

    唯一的区别就是这个$O(n^3)$能过

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (ll i=j;i<=k;++i)
    #define D(i,j,k) for (ll i=j;i>=k;--i)
    #define ll long long
    #define mp make_pair
    #define maxn 205
    const ll md=1000000007;
     
    ll h[maxn],to[maxn],ne[maxn],en=0,n;
    ll lim[maxn],siz[maxn],tmp[maxn];
    ll dp[maxn][maxn],c[maxn][maxn];
    char s[maxn];
     
    void add(ll a,ll b)
    {to[en]=b;ne[en]=h[a];h[a]=en++;}
     
    ll C(ll n,ll m)
    {
        if (n<0||m<0)
        {
            return 0;
        }
        return c[n][m];
    }
     
    void Tree_DP(ll o)
    {
        dp[o][1]=1;siz[o]=1;
        for (ll i=h[o];i>=0;i=ne[i])
        {
            Tree_DP(to[i]);
            F(j,0,siz[o]+siz[to[i]]+2) tmp[j]=0;
            F(j,1,siz[o]) F(k,1,siz[to[i]]) F(_j,j,siz[to[i]]+siz[o])
            if (dp[o][j]&&dp[to[i]][k])
            {
                if (lim[to[i]]==1)
                {
                    if (siz[o]+siz[to[i]]-_j>=siz[to[i]]-k+1+siz[o]-j&&_j>=j)
                    {
                        tmp[_j]+=(((ll)dp[o][j]*dp[to[i]][k])%md*C(_j-1,j-1))%md*C(siz[o]+siz[to[i]]-_j,siz[o]-j)%md;
                        tmp[_j]%=md;
                    }
                }
                else
                {
                    if (_j>=j+k&&siz[o]+siz[to[i]]-_j>=siz[o]-j)
                    {
                        tmp[_j]+=(((ll)dp[o][j]*dp[to[i]][k])%md*C(_j-1,j-1))%md*C(siz[o]+siz[to[i]]-_j,siz[o]-j)%md;
                        tmp[_j]%=md;
                    }
                }
            }
            siz[o]+=siz[to[i]];
            F(j,0,siz[o]) dp[o][j]=tmp[j];
        }
    }
     
    void Finout()
    {
        freopen("in.txt","r",stdin);
        freopen("wa.txt","w",stdout);
    }
     
    int main()
    {
        memset(h,-1,sizeof h);
        scanf("%lld",&n);
        scanf("%s",s+2);
        c[1][0]=1;c[1][1]=1;c[0][0]=1;
        F(i,2,maxn-1)
        {
            c[i][0]=1;
            F(j,1,maxn-1) c[i][j]=(c[i-1][j]+c[i-1][j-1])%md;
        }
        F(i,2,n)
        {
            add(i/2,i);
            switch(s[i])
            {
                case '<': lim[i]=1; break;
                case '>': lim[i]=-1;break;
            }
        }
        Tree_DP(1);
        ll ans=0;
        F(i,0,n) (ans+=dp[1][i])%=md;
        printf("%lld
    ",ans);
    }
    

      

  • 相关阅读:
    跨域访问方法列举 jsonp 和 客户端
    session 垃圾回收机制
    php 根据数据权重,得分或者持有数量等进行均衡分配给定数量分配方法
    进程和线程比较
    redis 过期策略分析
    redis 基础知识详解
    tcp/ip 协议
    ip 协议详解
    php redis 分布式类
    nginx打开目录游览功能
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6736895.html
Copyright © 2020-2023  润新知