NOIP2005 等价表达式(栈模拟简单计算器)

20960:等价表达式分数: 40

时间限制:1 秒
内存限制:125 兆
特殊判题: 否
提交:13
解决: 0

标签

  • NOIP

题目描述

明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。

这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?

这个选择题中的每个表达式都满足下面的性质:

1.表达式只可能包含一个变量‘a’。

2.表达式中出现的数都是正整数,而且都小于10000。

3.表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)

4.幂指数只可能是1到10之间的正整数(包括1和10)。

5.表达式内部,头部或者尾部都可能有一些多余的空格。

下面是一些合理的表达式的例子:

((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9...


输入格式

每组输入数据的第一行给出的是题干中的表达式。第二行是一个整数n(2<=n<=26),表示选项的个数。后面n行,每行包括一个选项中的表达式,表达式中没有空格。这n个选项的标号分别是A,B,C,D...

输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。


数据规模:

对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;

对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。

对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。


输出

每组输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。


样例输入

(a+1)^2
3
(a-1)^2+4*a
a+1+a
a^2+2*a*1+1^2+10-10+a-a

样例输出

AC

#include<iostream>
#include<cstring>
#include<stack>
#include<cstdio>
using namespace std;
#define MOD 111111111
int b[200];
long long atoi(char ch[])
{
    long long sum=0;
    int len=strlen(ch);
    for(int i=0;i<len;i++)
        sum=sum*10+ch[i]-'0';
    return sum;
}
long long hanshu(long long a , long long b ,char m)
{
    if(m=='+')
        a=a+b;
    else if(m=='-')
        a=a-b;
    else if(m=='*')
        a=(a*b)%MOD;
    else
    {
        for(int j=1,temp=a; j<b; j++)
            a=(a*temp)%MOD;
    }
    return a%MOD;
}
long long value(char str[])
{
    long long sum[100];
    char ch[100];
    stack <char> c;
    int p=0,len=strlen(str),count=0;
    for(int i=0,q=0;i<len;i++)
    {
        if(str[i]=='a')
            sum[++p]=-2;
        else if(str[i]>='0'&&str[i]<='9')//转化成整数
        {
            ch[q++]=str[i];
        }
        else
        {
            ch[q]='\0';
            if(q!=0)
               sum[++p]=atoi(ch);
            q=0;
            if(str[i]==' ')
                continue;
            else
            {
                if(str[i]=='(')
                    count++;
                if(str[i]!=')')
                    c.push(str[i]);
                if(str[i]==')'&&count!=0)//匹配括号
                {
                    char m=c.top();
                    while(m!='(')//把括号里的运算符算完
                    {
                        sum[p-1]=hanshu(sum[p-1],sum[p],m);
                        p--;
                        c.pop();
                        m=c.top();
                    }
                    c.pop();
                    count--;
                    continue;
                }
                int lenc=c.size();
                while(lenc>1)//当栈大于1就可以比较操作要不要执行
                {
                    char m=c.top();
                    c.pop();
                    char n=c.top();
                    if(b[n]>=b[m]&&n!='(')
                    {
                        sum[p-1]=hanshu(sum[p-1],sum[p],n);
                        p--;
                        c.pop();
                        c.push(m);
                    }
                    else
                    {
                        c.push(m);
                        break;
                    }
                    lenc=c.size();
                }
            }
        }
        if(i==len-1&&q!=0)//数字结束处理
        {
            ch[q]='\0';
            sum[++p]=atoi(ch);
        }
    }
    while(p!=1)//栈里面可能还有操作符,当p==1时就不要管了
    {
        char m=c.top();
        sum[p-1]=hanshu(sum[p-1],sum[p],m);
        p--;
        c.pop();
    }
    return sum[p];
}
int main()
{
    char str[100];
    b['(']=5,b['^']=4,b['*']=3,b['+']=2,b['-']=2,b[')']=1;
    gets(str);
    long long ans;
    ans=value(str);
    int n;
    cin>>n;
    getchar();
    char ch[100];
    for(int i=0; i<n; i++)
    {
        gets(ch);
        if(value(ch)==ans)
            printf("%c",'A'+i);
    }
    cout<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值