【题目链接】

https://www.luogu.org/problem/P1310

题目描述

对于1 位二进制变量定义两种运算:

运算的优先级是:

  1. 先计算括号内的,再计算括号外的。

  2. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算。例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算。

现给定一个未完成的表达式,例如_+(_*_),请你在横线处填入数字00或者11 ,请问有多少种填法可以使得表达式的值为00。

输入格式

共 2 行。

第1 行为一个整数 LL,表示给定的表达式中除去横线外的运算符和括号的个数。

第2 行为一个字符串包含 LL 个字符,其中只包含’(’、’)’、’+’、’*’这44 种字符,其中’(’、’)’是左右括号,’+’、’*’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序给出了给定表达式中除去变量外的运算符和括号。

输出格式

共1 行。包含一个整数,即所有的方案数。注意:这个数可能会很大,请输出方案数对1000710007取模后的结果。

输入输出样例

输入 #1

4
+(*)
输出 #1

说明/提示

【输入输出样例说明】

给定的表达式包括横线字符之后为:_+(_*_)

在横线位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 时,表达式的值均为0 ,所以共有3种填法。

【题解】

1、转变为后缀表达式的形式,然后,如果是操作数要添加一个数字,记住第一个位置要多添加一个‘.’

2、然后进行推导,把四种情况的转移状态写清楚。

参考题解中duyi

第一步:中缀转后缀

后缀表达式是什么呢?参见洛谷P1449

这里先给大家介绍一下中缀表达式转后缀表达式的一般方法:

中缀表达式a + b*c + (d * e + f) * ga+b∗c+(d∗e+f)∗g,其转换成后缀表达式则为a b c * + d e * f + g * +abc∗+de∗f+g∗+。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

备注:本题中我们用一个"."来代表数字。扫描整个表达式(读入的字符串),如果当前位置不是括号(既不是左括号也不是右括号),就在后缀表达式里填一个"."表示这里应有一个数字。

第二步:DP

状态转移方程很好想:

如果当前是"*":

f[0][now]=f[0][now]∗f[0][last]+f[0][now]∗f[1][last]+f[1][now]∗f[0][last]

f[1][now]=f[1][now]∗f[1][now]

(注意两式顺序不能颠倒,因为1式中需要用到f[1][now]f[1][now]的原始值)

如果当前是"+":

f[1][now]=f[1][now]∗f[1][last]+f[0][now]∗f[1][last]+f[1][now]∗f[0][last]

f[0][now]=f[0][now]∗f[1][last]

(两式的顺序同样不能颠倒)

其中,f[i][j]表示j号数字是i的情况有多少种,初始化为1


【代码】

 #include<bits/stdc++.h>
using namespace std;
const int mod = ;
const int N = 1e5+; int f[][N] ; int priority( char s ){
switch ( s ){
case '+' : return ;
case '*' : return ;
case '(' :
case ')' : return -;
}
} void toSuffixString( string &s ){
int len = s.length(); string res = "." ;
stack < int > Op ; for(int i=;i<len ;i++){
/*if( s[i] == '.') {
res += ".";
}else */
if( s[i] == '(' || s[i] == '*' ){
Op.push(s[i]);
}else if( s[i] == ')' ){
while( !Op.empty() && Op.top() != '(' ){
res += Op.top();
Op.pop();
}
//出来的时候,栈顶为(.
Op.pop();
}else{
while( !Op.empty() && priority(Op.top()) >= priority(s[i]) ){
res += Op.top();
Op.pop();
}
//出来的时候,栈里面的运算符优先级低于当前位置.
Op.push( s[i] ) ;
}
if( !(s[i] == '(' || s[i] == ')') ){
res += ".";
}
}
while( !Op.empty() ){
res += Op.top();
Op.pop();
}
//cout << res << endl ;
s = res ;
} void Calc( string s ){
//cout << s << endl ;
int j = ;
int len = s.length();
for(int i= ; i < len ; i++ ){
if( s[i] == '.' ){
j ++ ;
f[][j] = f[][j] = ;
}else if( s[i] == '*' ){
j -- ;
f[][j] =(f[][j] * f[][j+] +
f[][j] * f[][j+] +
f[][j] * f[][j+] ) % mod ; f[][j] = (f[][j] * f[][j+]) % mod ; }else if( s[i] == '+' ){
j -- ;
f[][j] =(f[][j] * f[][j+] +
f[][j] * f[][j+] +
f[][j] * f[][j+] ) % mod ; f[][j] =(f[][j] * f[][j+] ) %mod ;
}
}
cout << f[][] << endl;
} int main(){
ios_base :: sync_with_stdio( false );
cin.tie(NULL) , cout.tie(NULL) ;
int n ;
string str ;
cin >> n >> str ;
toSuffixString(str);
Calc(str);
return ;
}

【数据结构】P1310 表达式的值的更多相关文章

  1. 洛谷 P1310 表达式的值 解题报告

    P1310 表达式的值 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. "× "运算优先于"⊕"运算,即计算表 ...

  2. 洛谷P1310 表达式的值

    P1310 表达式的值 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例 ...

  3. P1310 表达式的值

    P1310 表达式的值 题解 1.假设有两个布尔变量 x , y  x0表示使得x=0的方案数 x1表示使得x=1的方案数 y0表示使得y=0的方案数 y1表示使得y=1的方案数 | 按位或 & ...

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

    P1310 表达式的值 题目描述 给你一个带括号的布尔表达式,其中+表示或操作|,*表示与操作&,先算*再算+.但是待操作的数字(布尔值)不输入. 求能使最终整个式子的值为0的方案数. 题外话 ...

  5. luogu P1310 表达式的值

    题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ...

  6. 【洛谷P1310 表达式的值】

    题目链接 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式 ...

  7. 洛谷P1310 表达式的值 题解 栈/后缀表达式的应用

    题目链接:https://www.luogu.org/problem/P1310 本题涉及算法:栈.前缀表达式转后缀表达式,动态规划思想. 这道题目我思考了好长时间,第一时间让我做的话我也做不出来. ...

  8. 洛谷P1310 表达式的值——题解

    题目传送 题的难点:1.有运算优先级,不好判断.2.有破坏整体和谐性的讨厌的括号.3.不知道哪里要填数.4.要求方案数很大,搜索不会做呐. 发现难点1和2都是中缀表达式的缺点.转成后缀表达式后难点1. ...

  9. P1981 表达式求值

    P1981 表达式求值 题解 这个题联想一下  P1310 表达式的值  思路就是输入中缀式,转成后缀式,然后按后缀式计算,完美!!       but!! 会严重RE,因为你可能会输入中缀式的时候输 ...

随机推荐

  1. codeforces#1234F. Yet Another Substring Reverse(子集dp)

    题目链接: https://codeforces.com/contest/1234/problem/F 题意: 给出一个只包含前20个小写字母的字符串,一次操作可以让一段字符颠倒顺序 最多一次这样的操 ...

  2. Windows Form, Ok, Cancel button

    1. 为button设置DialogResult property为非None值, 可以关闭父窗口,并使父窗口的DialogResult property返回相应的值. http://msdn.mic ...

  3. 多进程之间的互斥信号量的实现(Linux和windows跨平台)

    最近工作中遇到了一些关于文件读取权限的问题.当一个程序中对一个固定名称的文件做了读写的操作的时候,外界通过并发式的调用这个应用的时候,可能存在多个进程同时去操作这个文件,这个时候可能会造成调用失败的问 ...

  4. [Oracle]关于回滚段的一些转贴摘录

    ORACLE 回滚段 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段 ...

  5. Tomca的启动与关闭

    点击startup.bat启动,遇到一闪而过的问题,可能尚未配置JAVA_HOME 8080端口被占用导致启动失败 关闭Tomcat的三种方式 * 点击x (不推荐) * 双击shutdown.bat ...

  6. 怎么通过原生JS改变元素的class属性

    解决方法:document.getElementById('test').className = 'emphasis' Eg: <!doctype html> <html lang= ...

  7. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_1.页面发布-需求分析

    先静态化,并存储到gridFS 然后,发消息给MQ,MQ接收到消息通知给所有监听他的Cms Client. Cms client从gridFS读取页面下载到自己的服务 业务流程如下:1.管理员进入管理 ...

  8. python中关于with以及contextlib的使用

    一般在coding时,经常使用with来打开文件进行文件处理,然后无需执行close方法进行文件关闭. with open('test.py','r' as f: print(f.readline() ...

  9. WPS--world使用格式刷

    1.在空白处左键点击一下即可出现格式刷

  10. Flutter参数的传递和接收

    上次只写了方法和参数,这次写了完整的示例,页面间参数的传递和接收的示例. 1.参数传递 用在程序上解释就是比如你进入一个商品选择列表,当你想选择一个商品的具体信息的时候,你就要传递商品编号,详细页面接 ...