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\n",ans);
}

  

posted @ 2017-04-20 08:58  SfailSth  阅读(538)  评论(1编辑  收藏  举报