P10956 金字塔
虽然我还是看题解才会做的(菜),但我还要说这题挺简单的(菜),还是菜就多练。
因为是对一个字符串操作求树的可能数,所以考虑区间dp,设状态 \(dp[i][j]\) 为区间 \(i\) 到 \(j\) 树的状态数。
在转移的过程中如果 \(s_i=s_j\) 时代表这可能为同一个根节点组成的树,所以才可以开始枚举中间点,当中间点与根节点的颜色相同时,我们就可以将分为两个子树,然后根据乘法原理,将每个区间状态数相乘就是这么划分的方案数,再将所有的状态数相加就得到了大区间的状态数,转移方程为 \(dp[i][j]=(dp[i][j]+dp[i][k]\times dp[k+1][j-1])\),\(k+1\) 和 \(j-1\) 是为了得到两个不同子树乘积。
#include <bits/stdc++.h> using namespace std; #define ll long long const int mod=1e9; const int N=1e5; char s[N]; int n; ll dp[1005][1005]; int main(){ ios::sync_with_stdio(false); cin>>s+1; n=strlen(s+1); for(int i=1;i<=n;i++){ dp[i][i]=1;//初始化,只有1种可能 } for(int len=2;len<=n;len++){//区间长度 for(int i=1;i<=n-len+1;i++){//枚举起点 int j=i+len-1; if(s[i]==s[j]){//可能合法 for(int k=i;k<=j-1;k++){//枚举中间点 if(s[k]==s[i]){//得到两个子树 dp[i][j]+=(dp[i][k]*dp[k+1][j-1])%mod; dp[i][j]%=mod; } } } } } cout<<dp[1][n]; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」