2013NOIP普级组第二题--表达式的值(参考洛谷题解)

一、题目描述

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。

输入输出格式

输入格式:

输入文件为 expr.in。

输入仅有一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘法运算符“*”,且没有括号,所有参与运算的数字均为 0 到 2^31-1 之间的整数。输入数据保证这一行只有 0~ 9、+、*这 12 种字符。

输出格式:输出文件名为 expr.out。

输出只有一行,包含一个整数,表示这个表达式的值。注意:当答案长度多于 4 位时,

请只输出最后 4 位,前导 0 不输出。

输入输出样例

输入样例#1:  复制
1+1*3+4
输出样例#1:  复制
8
输入样例#2:  复制
1+1234567890*1
输出样例#2:  复制
7891
输入样例#3:  复制
1+1000000003*1
输出样例#3:  复制
4









说明

对于 30%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100;

对于 80%的数据,0≤表达式中加法运算符和乘法运算符的总数≤1000;

对于 100%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100000。

二、解题思路

思路一

到题目,首先分析:

1、乘法一定先做

2、而所有的连乘都是从左往右算

3、更重要的是,如果遇到加号,说明连乘必定完结,这时候再累加即可

定义——块:一段连乘

首先,题目中必有x个加号,将式子分为x+1个块,而这些块最终要做的是相加,所以从左往右算用ans表示当前累加和,t1表示累乘结果,t2表示当前这个数(当前要乘的数),t2的读入方式类似C++的读入优化,按位读入然后乘以10加当前位

框架

do ch=getchar()  

switch(ch)  

case'+':ans累加  

case'*':t1累乘

思路二

   输入可以直接scanf(“%d”),然后scanf(“%c”)就行了,不会出错。每一次判断其上一个运算符,进行相应的处理,然后添加到sum中。这里注意一下,如果开int,有可能两个2^31-1相乘,这样可能(我也没试过)会爆。所以都用long long存,保证能AC。最后如果scanf(“%c”)==EOF,则进行最后的处理,然后break即可。只输出后四位,则每一步操作都mod10000即可。

思路三

栈(stack)

(1)读入字符,当其为”+“时,我们先不管;当其为数时则入栈;当其为“*”时我们继续往后读一个数,再从栈中取出一个数与其相乘,将其乘积入栈;

(2)第一项执行完毕后,我们将栈中的元素累加,再输出和。显然,这就是我们想要的答案。

三、参考代码

(1)非栈的思想实现 

#include<cstdio>

#include<iostream>

#include<algorithm>

#include<cmath>

#include<cstring>

#include<string>

using namespace std;

int main()

{

    long long shu,sum=0,cj,sg;//记得sum初始值赋为0;cj为其中一段运算(即一段连续的乘积)的值

    char ch=0,xg;//ch存储上一个运算符,xg为新读入的运算符

    bool tf=true;

    while(tf)

    {

        scanf("%lld",&shu);

        tf=scanf("%c",&xg)==1?true:false;//如果下一个没有运算符了,则tf=false,既保证了此次循环的正常运行,又能在下一遍循环跳出

        if(ch==0)cj=shu;//如果是刚开始读入,则直接赋值

        if(ch=='+')sum=(sum+cj)%10000,cj=shu;//如果上一个操作是加法,则将前一段的值加入到sum中,然后再更新此新段的值

        if(ch=='*')cj=(cj*shu)%10000;//如果上一个运算仍是乘法,则将此数乘入本段的值中

        if(!tf)sum=(sum+cj)%10000;//如果是最后一个元素,则进行最后的更新

        ch=xg;//将下一个读入的运算符作为新的一个循环的上一个运算符,并继续循环

    }

    printf("%lld",sum);//输出

    return 0;

}

 (2)栈的思想实践

#include<cstdio>

#include<iostream>

#include<cstring>

#include<stack>                                         //c++自带栈在STL模板库里调用

using namespace std;

string x;

stack <char> s;                                                               //算符栈

stack <long long> n;                                                      //数字栈

long long ans;

int len;

int main()

{

    int i=0;

    getline(cin,x);

    len=x.length();

    while (i<=len-1)

    {

        int t=0;

        bool f=false;

        while (x[i]>='0'&&x[i]<='9')                                          //进数字的操作

        {

            t=t*10+(x[i]-48);

            f=true;

            i++;

        }

        if (f)

        {

            n.push(t%10000);

            if (s.size()>=1&&s.top()=='*')                                               //处理乘号

            {

                int k=n.top();                                                              

                s.pop();

                n.pop();                                                  //先把top的数出栈,再让top-1的数成为top,让他们相乘,再让top出栈,让乘积进栈

                k*=n.top();                                                     //这几行码核心内容就是n[--top]=n[top]*n[top+1];

                n.pop();

                n.push(k%10000);

            }

        }

        if (x[i]=='+'||x[i]=='*')

        {

            s.push(x[i]);

            i++;

        }

    }

    int size=n.size();

    for (i=1;i<=size;i++)                                                                      //计算和

    {

        ans+=n.top();

        n.pop();

        ans%=10000;

    }

    printf("%lld",ans%10000);

    return 0;

}




  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值