2011NOIP普及组真题 4. 表达式的值

2024-05-05 07:44

本文主要是介绍2011NOIP普及组真题 4. 表达式的值,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线上OJ:

一本通::http://ybt.ssoier.cn:8088/problem_show.php?pid=1956

核心思想1:

1、本题考的是表达式树。完整的方法可以先建树,然后再计算的方式。
2、但是本题涉及的运算符并不多,故也可以用栈来直接模拟计算。符号放入符号栈,数值放入数值栈
3、本题要求的是最终结果为 0 的方案数,鉴于如下原则

如果是 c=a+b,仅当 a=0, b=0时, c=0。a和b只要有一个为1,则 c=1
如果是 c=a*b,仅当 a=1, b=1时, c=1。a和b只要有一个为0,则 c=0
故,若a[0]、b[0]表示各自节点数值为0的方案数;a[1]、b[1]表示各自节点数值为1的方案数

+号时:
c [ 0 ] = a [ 0 ] ∗ b [ 0 ] c[0] = a[0] * b[0] c[0]=a[0]b[0]
c [ 1 ] = a [ 1 ] ∗ b [ 0 ] + a [ 1 ] ∗ b [ 1 ] + a [ 0 ] ∗ b [ 1 ] c[1] = a[1]*b[0] + a[1]*b[1] +a[0]*b[1] c[1]=a[1]b[0]+a[1]b[1]+a[0]b[1]

*号时:
c [ 0 ] = a [ 0 ] ∗ b [ 0 ] + a [ 1 ] ∗ b [ 0 ] + a [ 0 ] ∗ b [ 1 ] c[0] = a[0] * b[0] + a[1]*b[0] + a[0]*b[1] c[0]=a[0]b[0]+a[1]b[0]+a[0]b[1]
c [ 1 ] = a [ 1 ] ∗ b [ 1 ] c[1] = a[1] * b[1] c[1]=a[1]b[1]

4、综上所述,数值节点存储的应该是数组 a[0], a[1], 分别表示当前节点为0的方案总数为1的方案总数

核心思想2:

对于每一个待入栈的符号 s[i]
1、如果是左括号,则直接入栈
2、如果是右括号,则把符号栈内的符号全部算完,直到遇到第一个左括号时停止。然后把第一个左括号弹出(右括号也不入栈,相当于抵消一对括号)
3、如果是运算符
3.1 如果栈为空,直接入栈
3.2 如果栈顶是左括号,直接入栈
3.3 如果栈顶符号优先级更低或相同,直接入栈
3.4 如果栈顶符号优先级高,则把栈顶高优先级的符号全部算完,直至遇到第一个优先级更低或相同停止。然后符号入栈
3.5 注意1:栈顶不会遇到右括号,因为右括号和左括号已经抵消了
3.6 注意2:本题不需要校验表达式的合法性,否则还需要考虑括号要匹配;第一个不能是右括号;最后一个不能是左括号
4、叶子节点的数值都存入 {1,1},因为叶子节点放0则为0,放1则为1,所以叶子节点值为0和1的总方案数都是1

题解代码:
#include <bits/stdc++.h>
#define MOD 10007
using namespace std;stack<char> op;
stack<vector<int>> num; // num[0]表示该节点为0的方案数;num[1]表示该节点为1的方案数int n;
string s;int pri[128];
void inipri()
{pri['+'] = 3; pri['*'] = 4;
}void cal()
{vector<int> a, b; // a, b为与 num 相同的结构 a = num.top();  // 数字栈取出第一个元素num.pop();      // 并弹出b = num.top();  // 数字栈取出第二个元素num.pop();      // 并弹出char c = op.top();  // 符号栈取出第一个运算符op.pop();       // 并弹出if(c == '+')  // 如果是+,则左右均为0的方案数的乘积为新的0的方案数;0*1+1*0+1*1为新的1的方案数num.push({(a[0] * b[0]) % MOD, (a[1]*b[1] + a[0]*b[1] + a[1]*b[0]) % MOD});else // 如果是*,则左右均为1的方案数的乘积为新的1的方案数;0*1+1*0+0*0为新的0的方案数num.push({(a[0]*b[0] + a[0]*b[1] + a[1]*b[0]) % MOD, (a[1] * b[1]) % MOD});
}int main()
{inipri(); // 初始化符号优先级cin >> n >> s;num.push({1, 1}); // 数字栈推的第一组数为 num[0]=1, num[1]=1。因为要么0,要么1,各有1种可能性for(int i = 0; i < n; i++){if(s[i] == '(')  op.push(s[i]); // 如果是左括号,则直接入符号栈else if(s[i] == ')')    // 如果是右括号(右括号的优先级最低){while( !op.empty() && op.top() != '(' )  cal(); // 则把符号栈内所有的运算符都算完,直到遇到第一个左括号op.pop(); // 然后弹出栈顶的左括号。这样就完成了一对括号之间的计算}else  // 如果读入的是*或者+{while( !op.empty() && pri[op.top()] > pri[s[i]] )  cal(); // 如果待入栈的符号优先级低于栈顶的符号,则把高优先级的运算符先计算op.push(s[i]);       // 符号加到栈中num.push({1, 1}); // 每次新增的叶子节点放 0和1的方案数都是 1}}while ( !op.empty() )  cal(); // 把所有运算符都计算完cout << num.top()[0]; // 最后一个结果的[0] 即表示为0的方案总数return 0;
}

这篇关于2011NOIP普及组真题 4. 表达式的值的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961158

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

如何掌握面向对象编程的四大特性、Lambda 表达式及 I/O 流:全面指南

这里写目录标题 OOP语言的四大特性lambda输入/输出流(I/O流) OOP语言的四大特性 面向对象编程(OOP)是一种编程范式,它通过使用“对象”来组织代码。OOP 的四大特性是封装、继承、多态和抽象。这些特性帮助程序员更好地管理复杂的代码,使程序更易于理解和维护。 类-》实体的抽象类型 实体(属性,行为) -》 ADT(abstract data type) 属性-》成

Java基础回顾系列-第三天-Lambda表达式

Java基础回顾系列-第三天-Lambda表达式 Lambda表达式方法引用引用静态方法引用实例化对象的方法引用特定类型的方法引用构造方法 内建函数式接口Function基础接口DoubleToIntFunction 类型转换接口Consumer消费型函数式接口Supplier供给型函数式接口Predicate断言型函数式接口 Stream API 该篇博文需重点了解:内建函数式

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda

逻辑表达式,最小项

目录 得到此图的逻辑电路 1.画出它的真值表 2.根据真值表写出逻辑式 3.画逻辑图 逻辑函数的表示 逻辑表达式 最小项 定义 基本性质 最小项编号 最小项表达式   得到此图的逻辑电路 1.画出它的真值表 这是同或的逻辑式。 2.根据真值表写出逻辑式   3.画逻辑图   有两种画法,1是根据运算优先级非>与>或得到,第二种是采

将浮点型算式的中缀表达式转换成后缀表达式并算出式子结果

最近因为需要了解如何将在Win应用程序控制台输入的算式表达式转化成其后缀表达式的算法,所以在网上搜索了一下,看到许多人的程序都只是对应于运算数在0~9的范围内的整型运算式,所以自己就写了一个可以计算浮点型算式的程序,一下是运行时的截图: 式子中的a,b,c是可供用户自行输入的变量。 首先,我先对输入的运算符进行了简单的合法性判断,我的判断代 码如下: //函数的传入参

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ