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

清空全网题目系列 · 洛谷 · P1054 [NOIP 2005 提高组] 等价表达式

说明

说明

本系列由 Lee_King_Jimmy 推出,目的是将全网的题目都解一遍

这是第 444
上一篇: 清空全网题目系列 · SPOJ · Sum the Square
下一篇: 未完待续

题目位置

https://www.luogu.com.cn/problem/P1054

思路

首先我们讲解后缀表达式

后缀表达式

我们平时使用的表达式是中缀表达式,虽然我们自己看着很顺眼 试问在复杂的题目中的公式很顺眼吗?,但是计算机却不行 深有同感

后缀表达式就是一个没有括号,没有优先级的表达式,符号全部都在数字的后面。

计算后缀表达式

我们要使用一个栈,执行以下操作:

  • 遇到的是一个数字,我们将这个数字压到这个栈里面
  • 遇到的是一个符号,我们取出栈顶的两个数,将这两个数字运算后重新压入栈内

中缀表达式转后缀表达式

  • 如果为数,则直接添加到后缀表达式中。

  • 如果为运算符 +,-,*,^,则重复将“运算符栈”栈顶元素添加到后缀表达式中,再将“运算符栈”栈顶元素从“运算符栈”中弹出,直到“运算符栈”栈顶元素优先级小于该运算符优先级或“运算符栈”为空,再加入该运算符。

  • 如果为左括号 (,则直接加入“运算符栈”。

  • 如果为右括号 ),则重复弹出“运算符栈”栈顶元素,直到左括号 ( 也弹出。
    当表达式内所有元素处理完毕后,依次弹出“运算符栈”所有元素并添加到后缀表达式中。

接着

Q1: 怎么解决 a 这个未知数

我们可以计算出每一个后缀表达式的答案,a 可以取一个质数,比如 10007

Q2: 数据太大爆 long long

我们可以选择一个大质数作为模数
每一次计算取模即可,注意减法要减去之后加上这个模数再次模一遍

Q3: 为什么会 RE

因为输入数据的时候我们要使用 getchar 输入数据,如果使用 gets getline 等读取一行的函数,字符串的末尾会多出一个 \r, 详细见代码

实现代码

#include <stdio.h>
#include <ctype.h>// 一个数字栈
long long num_st[1024], top_num = 0;
// 一个符号栈
char sign_st[1024]; int top_sign = 0;typedef long long ll;
const int MOD = 1e9 + 7, A = 100007;    // MOD 要是一个质数, A=91?一个随机的数字ll power(ll x, ll y) {if(!y) return 1;ll tmp = power(x, y >> 1);(tmp *= tmp) %= MOD;if(y & 1) (tmp *= x) %= MOD;return tmp;
}
void OpCalc(char op) { // 计算数字栈的栈顶两个数使用 op 符号的答案ll b = num_st[top_num--]; // 栈顶元素switch (op) {case '+': num_st[top_num] = (num_st[top_num] + b) % MOD; break;case '-': num_st[top_num] = (num_st[top_num] - b + MOD) % MOD; break; // 注意负数case '*': num_st[top_num] = (num_st[top_num] * b) % MOD; break;case '^': num_st[top_num] = power(num_st[top_num], b); break;}
}
int get(char x) {if (x == '+' || x == '-') return 1;if (x == '*') return 2;if (x == '^') return 3;return 0;
}// 读入一个表达式并且计算
char str[1024] = {0};
int cur = 0;ll p()
{char ch; top_num = top_sign = 0; // 将两个栈置为空while ((ch = getchar()) == '\n' || ch == '\r'); // 将换行符吃了do {int tmp_val = 0, ck = false;while (isdigit(ch)) tmp_val = (tmp_val * 10 + (ch - '0')) % MOD, ch = getchar(), ck = true; // 这里要 mod, 这里是读入表达式中的数字if (ck) num_st[++top_num] = tmp_val; // 保存答案if (ch == '\n' || ch == '\r') break; // 该退出了if (ch == 'a') num_st[++top_num] = A; // A 的值// 处理符号if (ch == '(') sign_st[++top_sign] = '(';else if (ch == ')') { // 处理右括号while (top_sign && sign_st[top_sign] != '(') OpCalc(sign_st[top_sign--]); // 计算元素top_sign--; // 注意这里还是要--, 删除最后的左括号}else if (ch == '+' || ch == '-' || ch == '*' || ch == '^')// +, -, *, ^{while (top_sign && get(ch) <= get(sign_st[top_sign])) OpCalc(sign_st[top_sign--]); // 计算元素sign_st[++top_sign] = ch; // 保存当前这个符号}} while ((ch = getchar()) != '\n' && ch != '\r'); // 不是换行符while (top_sign) OpCalc(sign_st[top_sign--]); return num_st[1];
}int main()
{// freopen("equal.in", "r", stdin);// freopen("equal.out", "w", stdout);ll sample = p();printf("%s", str);int n;scanf("%d", &n);for (int i = 0; i < n; i++){if (p() == sample) putchar('A' + i);}return 0;
}

时间复杂度分析

时间复杂度为 O(nT)O(nT)O(nT) TTT 表示字符串的长度
最大数据为 O(26×50)=O(1300)O(26 \times 50) = O(1300)O(26×50)=O(1300) 水过,跑出 1ms1ms1ms 的高速

http://www.dtcms.com/a/452884.html

相关文章:

  • 偏振光阴影投影的三元光学逻辑处理器
  • GitLab 安装指南
  • 磁共振成像原理(理论)20:K空间采样 (Sampling of k-Space) - 采样定理
  • 安装wslgui
  • 激光+摄像头:打造高精度视觉测量系统
  • ie的常用网站渭南市建设局网站
  • 前端混入与组合实战指南
  • C++ 学习(3) ----设计模式
  • 畜牧业网站模板怎么做自己的网站平台
  • DAY 43 复习日-2025.10.7
  • 大数据毕业设计选题推荐-基于大数据的人体生理指标管理数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • Auricore亮相杭州RWA峰会,以黄金RWA重塑Web3新生态
  • 于飞网站开发免费推广软件工具
  • ChainVault闪耀杭州RWA峰会,黄金RWA重塑Web3新生态
  • [论文阅读] AI+软件工程(迁移)| 从JDK8到21:FreshBrew如何为AI代码迁移画上“可信句号”
  • 电信大数据实战:MySQL与Hadoop高效同步
  • 郑州经济技术开发区协同办公系统seo比较好的公司
  • FFmpeg开发笔记(十二):ffmpeg音频处理、采集麦克风音频录音为WAV
  • 金融大模型应用现状及未来趋势研究:国内外对比分析
  • AI 在金融、医疗、教育、制造业等领域都有广泛且深入的应用,以下是这些领域的一些落地案例
  • TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 变量(Variable)的定义与操作
  • AI行业应用:金融、医疗、教育、制造业领域的落地实践
  • 【Git 子模块冲突解析】
  • 软件设计师——09 数据库技术基础
  • Guava Cache 高性能本地缓存库详解与使用案例
  • 开源安全管理平台wazuh-阻止恶意IP访问
  • 蒲城做网站网站定制开发成本
  • 嵌入式开发入门:从 FreeRTOS 任务到通信协议(详细教程)
  • 数据结构(长期更新)第2讲:顺序表(一)
  • 《Flask 的“微”哲学:从轻量内核到请求上下文的深度剖析》