【Contest Hunter 5302】金字塔

【原题链接】传送门

【题解思路】

1.考虑如何将序列与树相对应,想到类似dfs序和欧拉序,同一个子树对应序列连续

2.暴力分子树过于复杂,考虑简化(划重点

  若当前区间为[l,r],考虑第一颗子树所在的区间为[l+1,k],然后剩下的若干区间存在于[k+1,r]中。

3.考虑状态的转移,合并两个状态需要乘法原理

4.考虑初值和边界

【code】

#include<bits/stdc++.h>
using namespace std;
#define File ""
#define inf 1<<30
#define ll long long
#define ull unsigned long long
#define rep(k,i,j) for(int k = i;k <= j; ++k)
#define FOR(k,i,j) for(int k = i;k >= j; --k)
inline void file(){
    freopen(File".in","r",stdin);
    freopen(File".out","w",stdout);
}
inline int read(){
    int x=0,f=1;   char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
const int mxn = 300+5;
const int mod = 1e9;
char s[mxn];
int n;
int f[mxn][mxn];

inline int solve(int  l,int r){
    if(l > r||s[l]!=s[r]) return 0;
    if(l == r) return 1;
    if(f[l][r]!=-1) return f[l][r];

    f[l][r] = 0;
    rep(k,l+2,r)
        f[l][r] = (f[l][r]+(ll)solve(l+1,k-1)*solve(k,r)%mod)%mod;
    return f[l][r];
}
int main(){
//    file();
    scanf("%s",s+1);
    n = strlen(s+1);
//    printf("%d\n",n);
    memset(f,-1,sizeof f);
//    rep(i,1,n) printf("(1,%d):%d\n",i,solve(1,i));
    printf("%d\n",solve(1,n));
    return 0;
}
/*
ABABABA
*/
View Code

 

posted @ 2019-04-22 20:48  ve-2021  阅读(148)  评论(0编辑  收藏  举报