2019.06.17课件:[洛谷P1310]表达式的值 题解

P1310 表达式的值

题目描述

给你一个带括号的布尔表达式,其中+表示或操作|*表示与操作&,先算*再算+。但是待操作的数字(布尔值)不输入。

求能使最终整个式子的值为0的方案数。

题外话

不久之前我在codewars上做过一道类似的题目。

o_1.png

以及把它搬运到了洛谷上。

o_2.png

o_3.png

布尔表达式计数问题

考虑这样一个问题:

有两个布尔变量\(x\)\(y\)

我们知道使\(x\)等于1的方案有\(x_1\)种,等于0的方案有\(x_0\)种;使\(y\)等于1的方案有\(y_1\)种,等于0的方案有\(y_0\)种。

那么:

使\(x\&y\)为1的方案数?为0的方案数?

使\(x|y\)为1的方案数?为0的方案数?

使\(x\oplus y\)(通常我们使用\(\oplus\)表示异或)为1的方案数?为0的方案数?

不难发现:

使\(x\&y\)为1,那么\(x\)\(y\)都要为1,所以方案数为\(x_1*y_1\)

使\(x\&y\)为0,那么\(x\)\(y\)不能都为1,所以方案数为\(x_1*y_0+x_0*y_1+x_0*y_0\)

使\(x|y\)为1的方案数为\(x_1*y_1+x_0*y_1+x_1*y_0\),为0的方案数为\(x_0*y_0\)

使\(x\oplus y\)为1的方案数为\(x_0*y_1+x_1*y_0\),为0的方案数为\(x_0*y_0+x_1*y_1\)

表达式树,前缀表达式,中缀表达式,后缀表达式

表达式树

o_4.png

\((1+2)*4\)

如上图,每个叶节点是一个数字,其他节点都是(双目)运算符。

整棵树表示一个表达式。每个子树表示一个子表达式。

计算这个表达式的方式如下图。

o_5.png

o_7.png

所以值为12。

中序遍历

中序遍历这个表达式树,我们发现得到的结果几乎和原来的表达式一样。

只是需要加一些括号罢了。

处理方法:我们可以给每个子树前后都加一对括号。

前/后序遍历

称前序遍历得到的式子为前缀表达式,或者波兰表达式。称后序遍历得到的式子为后缀表达式,或者逆波兰表达式。

前缀表达式和后缀表达式都拥有一个优秀的性质:不需要括号。

(下面仅以后缀表达式为例)

比如上文的\((1+2)*4\),改为后缀表达式就是:\(1\ 2\ +\ 4\ *\)

如何计算后缀表达式

我们可以用栈来处理:

遇到数字,入栈;遇到符号,从栈里取出两个数字,按照这个符号运算,然后把结果入栈。最后栈里剩下的就是结果。

\(1\ 2\ +\ 4\ *\)的计算过程如下:

1入栈1
2入栈12
1 2出栈,相加得3,3入栈3
4入栈34
3 4出栈,相乘得12,12入栈12

所以答案是12。

如何转化为后缀表达式

你可以直接建树,跑后序遍历。

但是这样又不好写,又慢。

我们考虑用栈维护。

遍历中缀表达式:

  1. 遇到数字,直接放入答案序列

  2. 遇到左括号,入栈

  3. 遇到右括号,把栈顶到上一个左括号的元素依次出栈并放入答案序列
  4. 遇到乘号,入栈
  5. 遇到加号,从栈顶开始弹出这段连续的乘号,并放入答案序列,最后加号入栈
  6. 最后把栈里剩下的元素依次放入答案序列

为什么是正确的?

模拟\(1+1*2*(1+2)+3*2*(1*5)+1\)

说明答案序列
1放入答案序列1
+入栈+1
1放入答案序列+11
*入栈+*11
2放入答案序列+*112
*入栈+**112
(入栈+**(112
1放入答案序列+**(1121
+入栈+**(+1121
2放入答案序列+**(+11212
出现),+出栈并放入答案序列,(出栈+**11212+
出现+,弹出栈顶的*并放入答案序列,然后+入栈++11212+**
3放入答案序列++11212+**3
*入栈++*11212+**3
2放入答案序列++*11212+**32
*入栈++**11212+**32
(入栈++**(11212+**32
1放入答案序列++**(11212+**321
*入栈++**(*11212+**321
5放入答案序列++**(*11212+**3215
出现),*出栈并放入答案序列,(出栈++**11212+**3215*
出现+,弹出栈顶的*并放入答案序列,然后+入栈+++11212+**3215***
1放入答案序列+++11212+**3215***1
剩余栈中元素放入答案序列11212+**3215***1+++

所以答案是11212+**3215***1+++。

正确性?
\[ \begin{aligned} 11212+**3215***1+++&=112(12+)**32(15*)**1+++\\ &=1123**325**1+++\\ &=11(23*)*3(25*)*1+++\\ &=116*3(10)*1+++\\ &=1(16*)(3(10)*)1+++\\ &=16(30)1+++\\ &=16(31)++\\ &=1(37)+\\ &=38\\ \\ 1+1*2*(1+2)+3*2*(1*5)+1&=1+2*3+6*5+1\\ &=1+6+30+1\\ &=38\\ \end{aligned} \]

P1310题解

首先在输入的表达式的恰当位置插入未知变量,然后转为后缀表达式。当然也可以一边转,一边插入未知变量。

之后,我们计算这个后缀表达式的值。不过维护的信息不再是表达式的值,而是使表达式值为0或1的方案数。

注意到单个变量为0或1的方案数为1.

#include <bits/stdc++.h>
using namespace std;
inline void read(int &num)
{bool flag = 0;num = 0;char c = getchar();while ((c < '0' || c > '9') && c != '-')c = getchar();if (c == '-'){flag = 1;c = getchar();}num = c - '0';c = getchar();while (c >= '0' && c <= '9')num = (num << 3) + (num << 1) + c - '0', c = getchar();if (flag)num *= -1;
}
inline void output(int num)
{if (num < 0){putchar('-');num = -num;}if (num >= 10)output(num / 10);putchar(num % 10 + '0');
}
inline void outln(int num)
{output(num);puts("");
}
inline void outln(string str)
{puts(str.c_str());
}
//以上为头文件和快读
const int mod = 10007;
const int N = 100001;
int n;
char str[N];            //输入的中缀表达式
stack<char> sta;        //转后缀表达式时使用的栈
string final;           //后缀表达式(答案序列)
stack<int> zero, one;   //zero维护使表达式值为0的方案个数,one维护使表达式值为1的方案个数
int main()
{read(n);scanf("%s", str + 1);final.push_back('n');                   //后缀表达式最开始应该有一个未知变量for (int i = 1; i <= n; i++){if (str[i] == '(' || str[i] == '*') //遇到左括号或乘号,入栈sta.push(str[i]);if (str[i] == '+')                  //遇到加号,弹出栈顶的乘号,然后加号入栈{while (!sta.empty() && sta.top() == '*'){final.push_back(sta.top());sta.pop();}sta.push(str[i]);}if (str[i] == ')')                  //右括号,把到上一个左括号的元素出栈放入答案序列{while (sta.top() != '('){final.push_back(sta.top());sta.pop();}sta.pop();}if (str[i] != '(' && str[i] != ')') //当不是左括号或者右括号时,应该插入一个未知变量{final.push_back('n');}}while (!sta.empty())                    //剩下的元素放入答案序列{final.push_back(sta.top());sta.pop();}for (char c : final)                    //遍历后缀表达式,这里使用了c++11的写法,相当于
//  for (int i = 0; i < final.size(); i++)
//  {   char c = final[i];{if (c == 'n')                       //单个变量,方案数为1{one.push(1);zero.push(1);}else{//rone表示右操作数(即上文中的y)为1的方案数(即上文中的y1),rzero同理int rone = one.top(), rzero = zero.top();one.pop();zero.pop();//同理int lone = one.top(), lzero = zero.top();one.pop();zero.pop();if (c == '*')   //与操作,为1需要都为1,为0需要不都为1{one.push(lone * rone % mod);zero.push((lone * rzero % mod + lzero * rone % mod + lzero * rzero % mod) % mod);}else            //或操作,为0需要都为0,为1需要不都为0{zero.push(lzero * rzero % mod);one.push((lone * rzero % mod + lzero * rone % mod + lone * rone % mod) % mod);}}}outln(zero.top());//需要整个表达式的值为0
}

转载于:https://www.cnblogs.com/water-lift/p/11038885.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362357.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue+element 封装日期范围组件(双向绑定)

像这样的日期组件&#xff0c;在后台管理项目中是比较多的&#xff0c;而且加了快捷选项&#xff0c;代码量较多&#xff0c;因此封装成组件。 封装这一类型的组组件&#xff0c;主要是了解输入框双向绑定 v-model 的过程。 1、了解输入框双向绑定的过程&#xff1a; 官网&am…

用Hystrix保护您的应用程序

在之前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中&#xff0c;我们讨论了微服务以及如何使用&#xff08;RxJava&#xff09;的Reactive Extensions编排微服务。 但是&#xff0c;如果一项或多项服务由于已被暂停或引发异常而…

若依 从下载到成功运行及打包

官网&#xff1a;http://www.ruoyi.vip/ 目录 一、下载并运行项目 二、关于 若依 接口地址配置 2.1 若依的跨域代理介绍 2.2 配置跨域代理&#xff0c;调用后台接口 2.2.1 配置 后台 ip 地址 2.2.2 页面报“系统接口404”错误 三、打包配置 3.1 打包之后静态资源404…

uniAPP小程序 子组件使用watch不生效,H5正常,小程序不正常(其实是子组件model选项的问题)

第一次用 uniapp 写小程序&#xff0c;还是遇到挺多问题的。写了一个下拉多选组件&#xff0c;发现同样的代码&#xff0c;在H5上运行效果正常&#xff0c;在小程序上压根不走 watch 。 uniapp官网&#xff1a;【全局配置 | uni-app官网】 看文档 watch 是支持H5、小程序的&…

jQuery EasyUI/TopJUI创建日期时间输入框

jQuery EasyUI/TopJUI创建日期时间输入框 日期时间输入框组件 HTML 和日期输入框类似&#xff0c;日期时间输入框允许用户选择日期和指定的时间并按照指定的输出格式显示。相比日期输入框&#xff0c;它在下拉面板中添加了一个时间微调器。 <div class"topjui-containe…

table 设置边框

本文引自&#xff1a;https://www.cnblogs.com/leona-d/p/6125896.html 示例代码&#xff1a; <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width…

uniapp小程序 设置自定义导航栏

如下截图&#xff0c;通过 wx.getSystemInfoSync 计算得到的整个导航栏高度&#xff0c;其实是有3个部分的&#xff1a; 黄色&#xff1a;状态栏高度&#xff0c;uniapp文档中有给出&#xff1b;红色&#xff1a;胶囊高度&#xff0c;可以计算得出&#xff1b;绿色&#xff1a;…

Akka Notes –演员记录和测试

在前两部分&#xff08; 一 &#xff0c; 二 &#xff09;中&#xff0c;我们简要讨论了Actor以及消息传递的工作方式。 在这一部分中&#xff0c;让我们看一下如何修复并记录我们的TeacherActor 。 概括 这就是我们上一部分中的Actor的样子&#xff1a; class TeacherActor …

vue笔记(二)Vue-class与style、事件、计算属性、数据监听、指令+自定义指令、过滤器

vue官网 一 、class、style操作 二、事件 三、计算属性 四、数据监听、观测 五、指令自定义指令 六、过滤器 一 、class、style操作 官网 1. class使用&#xff1a; &#xff08;1&#xff09;v-bind:class“数据|属性|变量|表达式” &#xff08;2&#xff09;v-bind:class“…

Nsum问题

题目 题解 暴力法 class Solution:def fourSum(self, nums: List[int], target: int) -> List[List[int]]:if len(nums) < 4:return []nums.sort()N len(nums)res []for i in range(N-3):for j in range(i1, N-2):for k in range(j1, N-1):for m in range(k1, N):tmp…

js笔记(一)js基础、程序结构、函数

大标题小节一、js 基础1. javascript的组成&#xff1b;2. 运行js&#xff1b;3. 打印信息&#xff1b;4. 关键字var&#xff1b;5. js中的数据类型&#xff1b;6. NaN&#xff08;not a number&#xff09;&#xff1b;7. js运算符&#xff1b;8. 数据类型转换&#xff1b;9. …

DB2 9 底子(730 考试)认证指南,第 3 局部: 拜访 DB2 数据(3)

建树第一个数据库First Steps在 DB2 的安顿进程中&#xff0c;会表示 First Steps 面板&#xff0c;它答运用户生成要操作的示例数据库&#xff1a; 选择 Database Creation 选项将表示一个附加菜单&#xff0c;可以建树 SAMPLE 数据库。 大大都用户希冀建树 SAMPLE 数据库并运…

新的自定义控件:TaskProgressView

我已经编写了一个新的自定义控件&#xff0c;并将其提交到ControlsFX项目。 这是一个高度专业的控件&#xff0c;用于显示后台任务&#xff0c;其当前状态和进度的列表。 这实际上是我为ControlsFX编写的第一个控件&#xff0c;只是出于乐趣的考虑&#xff0c;这意味着我自己没…

js笔记(三)ES5、ES5新增的数组的方法、字符串的方法、字符编码、对象的序列化和反序列化、bind

数组方法、字符串方法总结 大目录小目录一、ES5严格模式1. 严格模式&#xff1b;2. 严格模式的行为变更&#xff1b;二、ES5新增的数组的方法1. 判断是否为数组&#xff1a;Array.isArray()&#xff1b;2. 判断数组中是否存在某个值&#xff1a;indexOf(data, start)、lastInd…

SVG入门

1、简介 使用xml描述的矢量文件。 2、兼容性 https://caniuse.com/#searchsvg 3、使用方式 &#xff08;1&#xff09;浏览器直接打开 &#xff08;2&#xff09;html中使用img引用 <p><img src"simple.svg" width"50" height"50"…

js 值和引用

1、概述 简单值&#xff08;基本类型&#xff09;通过值复制的方式来赋值/传递。 复合值&#xff08;对象&#xff09;通过引用复制的方式来赋值/传递。 <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><title…

js笔记(六)事件、正则

数组方法、字符串方法总结 大标题小节一、事件1.1 事件&#xff1b;1.2 事件对象&#xff1b;1.3 键盘事件的keyCode&#xff1b;1.4 关于鼠标的尺寸&#xff1b;1.5 事件冒泡&#xff1b;1.6 事件的默认行为&#xff1b;1.7 事件监听&#xff1b;1.8 事件委托&#xff08;事件…

神州泰岳2050万元收买并增资奇点国际

网易科技讯 3月7日消息&#xff0c;神州泰岳来日诰日颁布发表关照公告&#xff0c;将经由股权让渡体例共付出1450万元股权让渡款获得奇点国际100%股权&#xff0c;同时神州泰岳与邵起明分别出资600万元、200万元对奇点国际举行增资。本次增资后&#xff0c;奇点国际注册资金增进…

拯救你丢失的精度——BigInteger和BigDecimal类(入门)

第三阶段 JAVA常见对象的学习 BigInteger和BigDecimal类 BigInteger类 (一) 构造方法&#xff1a; //针对超过整数范围的运算(整数最大值&#xff1a;2147483647) BigInteger(String val) (二) 常用方法&#xff1a; //加 public BigInteger add(BigInteger val) //减 public…

vue笔记(四)注册组件,路由,vuex

官网 一、项目中的组件注册 二、路由 三、vuex 一、项目中的组件注册 1. 全局 import Loading from /components/loading;//封装的loading组件 Vue.component(Loading,Loading);2. 局部 <loading/>important loading from ./components/loadingcomponents:{loading}二…