【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 */
G102的孤儿们都要好好的啊。