表达式求值【NOIP2013普及组】
表达式求值【NOIP2013普及组】
给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。
输入输出格式
输入格式:
输入仅有一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘法运算符“*”,且没有括号,所有参与运算的数字均为 0 到 2^31-1 之间的整数。输入数据保证这一行只有 0~ 9、+、*这 12 种字符。
输出格式:
输出只有一行,包含一个整数,表示这个表达式的值。注意:当答案长度多于 4 位时,
请只输出最后 4 位,前导 0 不输出。
输入输出样例
输入样例:
【输入样例 1】
1 + 1 ∗ 3 + 4 1+1*3+4 1+1∗3+4
【输入样例 2】
1 + 1234567890 ∗ 1 1+1234567890*1 1+1234567890∗1
【输入样例 3】
1 + 1000000003 ∗ 1 1+1000000003*1 1+1000000003∗1
输出样例:
【输出样例 1】
8 8 8
【输出样例 2】
7891 7891 7891
【输出样例 3】
4 4 4
提示信息
【输入输出样例说明】
- 样例 1 计算的结果为 8,直接输出 8。
- 样例 2 计算的结果为 1234567891,输出后 4 位,即 7891。
- 样例 3 计算的结果为 1000000004,输出后 4 位,即 4。
【数据范围】
- 对于 30%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100;
- 对于 80%的数据,0≤表达式中加法运算符和乘法运算符的总数≤1000;
- 对于 100%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100000。
想法:
我的思路非常简单,用的方法就很简单,先输入一个字符串,然后逐个将字符存入两个数组
s
h
u
z
i
shuzi
shuzi和
f
u
h
a
o
fuhao
fuhao总,分别表示数字和符号。
然后枚举每一位数和符号,先算乘法,将算过的数标记一下,在算加法就行了~~
代码:
代码可简单了~
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
using namespace std;
long long l,t,S,F,fuhao[200000],shuzi[200000];
string a;
int main()
{
//freopen ("expr.in","r",stdin);
//freopen ("expr.out","w",stdout);
cin >>a; l=a.size();
for (int i=0;i<l;i++)
{
if (!t)
{
shuzi[++S]=shuzi[S]*10+a[i]-48;
t=1;
}
else
{
if (a[i]>='0' && a[i]<='9')
shuzi[S]=shuzi[S]*10+a[i]-48;
else
{
shuzi[S]%=10000;
if (a[i]=='+')
fuhao[++F]=1;
else
fuhao[++F]=2;
t=0;
}
}
}
for (int i=1;i<=F;i++)
{
if (fuhao[i]==2)
{
fuhao[i]=-1;
shuzi[i+1]*=shuzi[i];
shuzi[i+1]%=10000;
shuzi[i]=-1;
}
}
int i=1,t1=1,t2=2;
while (i<=F)
{
while (shuzi[t1]==-1) t1++;
while (shuzi[t2]==-1 || t2<=t1) t2++;
while (fuhao[i]==-1) i++;
if (fuhao[i]==1)
{
shuzi[t2]+=shuzi[t1];
shuzi[t2]%=10000;
shuzi[t1]=-1;
fuhao[i]=-1;
}
}
cout <<shuzi[S];
// fclose(stdin);
// fclose(stdout);
return 0;
}
只有60多行,是不是很“短”呀?
但是你如果直接抄代码,你会发现,此代码在比较新的编译器下会全部错误答案,但在比较旧的编译器下可以AC!!
为什么呢?
这就涉及到编译器的问题了:
我们看第17行,
s
h
u
z
i
[
+
+
S
]
=
s
h
u
z
i
[
S
]
∗
10
+
a
[
i
]
−
48
;
shuzi[++S]=shuzi[S]*10+a[i]-48;
shuzi[++S]=shuzi[S]∗10+a[i]−48;
这一句在不同的编译器中会用不同的机器语言呈现:
1、旧版编译器:首先S增加1,然后计算后面的一串东西,然后再将这一串的结果存入数组中。
2、新版编译器:首先计算后面的一串东西,然后S增加1,然后将这一串的结果存入数组中。
这就导致计算的时候S还是旧的值,并没有+1,因此会得出错误的答案。
怎么改呢?
很简单,只要将第17行的
s h u z i [ + + S ] = s h u z i [ S ] ∗ 10 + a [ i ] − 48 ; shuzi[++S]=shuzi[S]*10+a[i]-48; shuzi[++S]=shuzi[S]∗10+a[i]−48;
改为两行:
S + + ; S++; S++;
s h u z i [ + + S ] = s h u z i [ S ] ∗ 10 + a [ i ] − 48 ; shuzi[++S]=shuzi[S]*10+a[i]-48; shuzi[++S]=shuzi[S]∗10+a[i]−48;
就可以了~
下面给出完整代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
using namespace std;
long long l,t,S,F,fuhao[200000],shuzi[200000];
string a;
int main()
{
//freopen ("expr.in","r",stdin);
//freopen ("expr.out","w",stdout);
cin >>a; l=a.size();
for (int i=0;i<l;i++)
{
if (!t)
{
S++;
shuzi[S]=shuzi[S]*10+a[i]-48;
t=1;
}
else
{
if (a[i]>='0' && a[i]<='9')
shuzi[S]=shuzi[S]*10+a[i]-48;
else
{
shuzi[S]%=10000;
if (a[i]=='+')
fuhao[++F]=1;
else
fuhao[++F]=2;
t=0;
}
}
}
for (int i=1;i<=F;i++)
{
if (fuhao[i]==2)
{
fuhao[i]=-1;
shuzi[i+1]*=shuzi[i];
shuzi[i+1]%=10000;
shuzi[i]=-1;
}
}
int i=1,t1=1,t2=2;
while (i<=F)
{
while (shuzi[t1]==-1) t1++;
while (shuzi[t2]==-1 || t2<=t1) t2++;
while (fuhao[i]==-1) i++;
if (fuhao[i]==1)
{
shuzi[t2]+=shuzi[t1];
shuzi[t2]%=10000;
shuzi[t1]=-1;
fuhao[i]=-1;
}
}
cout <<shuzi[S];
// fclose(stdin);
// fclose(stdout);
return 0;
}
看我这么细心,给我一个三连吧~~