洛谷 P1054 等价表达式

48 篇文章 0 订阅
12 篇文章 0 订阅

题目描述
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
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……
输入输出格式
输入格式:

输入文件equal.in的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。

输出格式:

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

输入输出样例
输入样例#1:
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
输出样例#1:
AC
说明
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。
2005年提高组第四题


思路就是枚举a的取值,比较计算结果是否相等。
坑点:
1 括号不匹配。
2 结果可能较大需要取模。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<stack>
using namespace std;
const long long md=1e9+7;
stack<long long>num;
stack<char>sym;
int n,ans[35];
long long stdd[35];
string s[35];
long long pw(long long x,long long y)
{
    long long z=1;
    for(long long i=1;i<=y;i++)
        z*=x,z%=md;
    return z;
}
string read()
{
    string ss="";
    char ch=getchar();
    while(ch=='\n'||ch=='\r'||ch==' ')
        ch=getchar();
    while(ch!='\n'&&ch!='\r')
    {
        if(ch!=' ')
            ss.push_back(ch);
        ch=getchar();
        if(ch==EOF)
            break;
    }
    return ss;
}
bool cmp(char t)
{
    if(sym.empty()||sym.top()=='(')
        return 1;
    if(sym.top()=='^')
        return 0;
    if(t=='^')
        return 1;
    if(sym.top()=='*')
        return 0;
    if(t=='*')
        return 1;
    return 0;
}
void calc()
{
    char z=sym.top();
    sym.pop();
    if(z=='('||z==')')
        return ;
    long long x=num.top();
    num.pop();
    long y=num.top();
    num.pop();
    if(z=='+')
        num.push(((long long)x+y)%md);
    else if(z=='-')
        num.push(((long long)y-x+md)%md);
    else if(z=='*')
        num.push(((long long)y*x)%md);
    else
        num.push(pw(y,x));
}
int main()
{
    s[0]=read();
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        s[i]=read();
    for(int i=0;i<=n;i++)
    {
        bool flg=0;
        for(int k=1;k<=10;k++)
        {
            for(int j=0;j<=s[i].length()-1;j++)
            {
                if(s[i][j]>='0'&&s[i][j]<='9')
                {
                    long long tmp=0;
                    while(s[i][j]>='0'&&s[i][j]<='9')
                    {
                        tmp=tmp*10+s[i][j]-'0';
                        j++;
                    }
                    j--;
                    num.push(tmp);
                }
                else if(s[i][j]=='a')
                    num.push(k);
                else if(s[i][j]=='(')
                    sym.push(s[i][j]);
                else if(s[i][j]==')')
                {
                    if(!sym.empty())
                    {
                        while(sym.top()!='(')
                        {
                            calc();
                            if(sym.empty())
                                break;
                        }
                        if(!sym.empty())
                            sym.pop();
                    }
                }
                else
                {
                    while(!cmp(s[i][j]))
                        calc();
                    sym.push(s[i][j]);
                }
            }
            while(!sym.empty())
                calc();
            if(i==0)
            {
                stdd[k]=num.top();
                num.pop();
            }
            else
            {
                if(num.top()!=stdd[k])
                {
                    flg=1;
                    num.pop();
                    break;
                }
                num.pop();
            }
        }
        if(!flg&&i!=0)
            ans[++ans[0]]=i;
    }
    for(int i=1;i<=ans[0];i++)
        printf("%c",ans[i]+'A'-1);
    printf("\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值