当前位置: 首页 > news >正文

【题解】Luogu P1310 [NOIP 2011 普及组] 表达式的值

题意

给定一个仅包含与或的中缀表达式,在每一个数值位填 0 或 1,求有多少种填法使得表达式的值为 0。

思路

统计方案数,首先考虑 DP。要想得知表达式的值,就要得知参与最后运算的两个值。这启示我们将中缀转后缀,建表达式树。

定义 \(f_{u,0}\) 为以 \(u\) 为根的子树的表达式为 \(0\)\(f_{u,1}\) 同理。根据 \(u\) 的运算符列出状态转移方程。如果 \(u\) 是与,那么仅当两个子树表达式的值都为 \(1\) 时该表达式才为 \(1\)。根据乘法原理,方案数为 \(f_{lson,1}\times f_{rson,1}\)。其余依此类推。

\(u\) 为或:

\[f_{u,0}=f_{lson,0}\times f_{rson,0} \]

\[f_{u,1}=f_{lson,1}\times f_{rson,1}+f_{lson,0}\times f_{rson,1}+f_{lson,1}\times f_{rson,0} \]

\(u\) 为与:

\[f_{u,0}=f_{lson,0}\times f_{rson,0}+f_{lson,0}\times f_{rson,1}+f_{lson,1}\times f_{rson,0} \]

\[f_{u,1}=f_{lson,1}\times f_{rson,1} \]

答案即为 \(f_{root,0}\)。每个叶子结点都可以填 \(0\)\(1\),因此初始值都为 \(2\)

注意在补完表达式时要注意添加空位的情况,仅当运算符左边为括号时在左边添位,右边不为括号时在右边添位。为了方便添位和转后缀时的出栈,为表达式整体套一层括号。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#define int long long 
using namespace std;
const int N=1e5+10;
const int p=10007;
const int Tm=1e6+1,Ad=1e6+2,lKh=1e6+3,rKh=1e6+4;
int L,tot,totb,tott,cnt;
stack<int> st,st2;
char s[N];
int t[3*N],b[3*N];
int lson[3*N],rson[3*N],w[3*N],v[3*N];
int f[3*N][2];
void dfs(int u){if(lson[u]) dfs(lson[u]);if(rson[u]) dfs(rson[u]);if(w[u]==Ad){f[u][0]=f[lson[u]][0]*f[rson[u]][0]%p;f[u][1]=((f[lson[u]][0]*f[rson[u]][1]%p+f[lson[u]][1]*f[rson[u]][0]%p)%p+f[lson[u]][1]*f[rson[u]][1]%p)%p;}else if(w[u]==Tm){f[u][0]=((f[lson[u]][0]*f[rson[u]][1]%p+f[lson[u]][1]*f[rson[u]][0]%p)%p+f[lson[u]][0]*f[rson[u]][0]%p)%p;f[u][1]=f[lson[u]][1]*f[rson[u]][1]%p;}
}
signed main(){scanf("%lld",&L);scanf("%s",s+2);L+=2;s[1]='(';s[L]=')';for(int i=1;i<=L;i++){if(s[i]=='*'){if(t[tot]==lKh) t[++tot]=++cnt;t[++tot]=Tm;if(s[i+1]!='(') t[++tot]=++cnt;}else if(s[i]=='+'){if(t[tot]==lKh) t[++tot]=++cnt;t[++tot]=Ad;if(s[i+1]!='(') t[++tot]=++cnt;}else if(s[i]=='(') t[++tot]=lKh;else t[++tot]=rKh;}for(int i=1;i<=tot;i++){if(t[i]==Tm){while(!st.empty()&&st.top()==Tm){b[++totb]=Tm;st.pop();} st.push(Tm);}else if(t[i]==Ad){while(!st.empty()&&(st.top()==Tm||st.top()==Ad)){if(st.top()==Tm) b[++totb]=Tm;else b[++totb]=Ad;st.pop();}st.push(Ad);}else if(t[i]==rKh){while(!st.empty()&&st.top()!=lKh){if(st.top()==Tm) b[++totb]=Tm;else b[++totb]=Ad;st.pop();}if(!st.empty()) st.pop();}else if(t[i]==lKh) st.push(lKh);else b[++totb]=t[i];}for(int i=1;i<=totb;i++){if(b[i]<Tm){tott++;w[tott]=b[i];f[tott][0]=f[tott][1]=1;st2.push(tott);}else if(b[i]==Tm){int x=st2.top();st2.pop();int y=st2.top();st2.pop();lson[++tott]=x;rson[tott]=y;w[tott]=Tm;st2.push(tott);}else{int x=st2.top();st2.pop();int y=st2.top();st2.pop();lson[++tott]=x;rson[tott]=y;w[tott]=Ad;st2.push(tott);}}dfs(tott);printf("%lld\n",f[tott][0]);return 0;
} 

时间复杂度 \(O(L)\)

http://www.gsyq.cn/news/89253.html

相关文章:

  • Flink学习笔记:状态类型和应用
  • 2025贵阳公墓/公益公墓top5推荐!贵阳优质生态陵园榜单发布,合规保障与人文关怀兼具的安息之所推荐 - 全局中转站
  • AI核心知识50——大语言模型之Scaling Laws(简洁且通俗易懂版)
  • MySQL 深分页查询优化实践与经验总结
  • 电机多目标优化与灵敏度分析:探索电机性能提升之道
  • 打造下一个爆款!专业短剧APP全栈开发解决方案,解锁万亿级市场红利
  • 毕业论文选题AI推荐:9大工具+热门方向合集
  • C51_AH3144霍尔传感器
  • 16 位 SAR ADC 逐次逼近型 ADC 模拟集成电路设计探秘
  • 5 分钟快速入门 Gitlab CI/CD
  • 【题解】Luogu P13885 [蓝桥杯 2023 省 Java/Python A] 反异或 01 串
  • 【笔记】Manacher
  • 电动汽车永磁同步电机的电磁设计与最优控制探索
  • 【题解】Luogu B4185 [中山市赛 2024/科大国创杯小学组 2023] 倍数子串/子串
  • 5 分钟快速入门 Github Actions
  • 虚函数虚表
  • 已有析音法
  • 告别排版困境!AI 写作到发布全自动化的完整方案
  • Docker 两大基石:Namespace 和 Cgroups
  • 9、Eclipse集成开发环境:C/C++开发全流程指南
  • Python银行客户数据流失预测SMOTE平衡数据实现神经网络、SVM、决策树、随机森林与超参数调优|附代码数据
  • 享搭提醒助手:数据变动实时预警,运营者业务状态“尽在掌握”
  • 26 avl树(下)
  • openvela——动态管理日志输出通道及其实现原理
  • 连接2026:十款远程控制软件真实力横评与选择指南
  • 可以把 Windows 从 C盘迁移到 SSD 吗?
  • Draco 3D压缩终极指南:如何高效处理大型3D模型文件
  • Overleaf插件定制实战指南:3分钟搞定编辑器功能优化
  • 15、Linux 系统下的邮件与即时通讯使用指南
  • javet 的使用