【洛谷 1054】[NOIP2005] 等价表达式

等价表达式

题目描述
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质: 1. 表达式只可能包含一个变量‘a’。 2. 表达式中出现的数都是正整数,而且都小于10000。 3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘’(乘),‘’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘’,然后是‘’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘’,‘^’以及小括号‘(’,‘)’都是英文字符) 4. 幂指数只可能是1到10之间的正整数(包括1和10)。 5. 表达式内部,头部或者尾部都可能有一些多余的空格。 下面是一些合理的表达式的例子: ((a^1) ^ 2)^3,aa+a-a,((a+a)),9999+(a-a)a,1 + (a -1)3,110^9…… 对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’; 对于其它的数据,四种运算符‘+’,‘-’,‘’,‘^’在表达式中都可能出现。 对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

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

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

样例输入
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
样例输出
AC
提示
[提交][状态]

洛谷链接

zufeoj
问题 C: 等价表达式
时间限制: 1 Sec 内存限制: 128 MB
提交: 23 解决: 7

[提交][状态][讨论版][命题人:外部导入]

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define maxn 100
using namespace std;
stack<ll> shu;
stack<char> ch;
int t, len, cnt, vis[30];
char a[maxn], b[maxn];
ll u[5], v[5];
ll w[5] = {223, 347, 127, 83, 61};
bool is_kuo(){
    stack<char> s;
    for(int i = 0 ; i < len ; ++ i){
        if(a[i] == '('){
            s.push(a[i]);
        }
        else if(a[i] == ')'){
            if(!s.empty())
                s.pop();
            else
                return false;
        }
    }
    if(!s.empty())
        return false;
    return true;
}
bool is_num(char a){
    if(a <= '9' && a >= '0') return true;
    else return false;
}
ll ksm(ll a, ll b, ll c)
{
    ll base = a % c, ans = 1;
    while( b )
    {
        if(b & 1)
            ans = (ans * base) % c;
        base = (base * base) % c;
        b >>= 1;
    }
    return ans % c;
}
int f(char c){
    if(c == '+' || c == '-') return 1;
    else if(c == '*' || c == '/') return 2;
    else if(c == '^') return 3;
    else if(c == '(') return 0;
    else return -1;
}
void cal(){
    ll x = shu.top(); shu.pop();
    ll y = shu.top(); shu.pop();
    char op = ch.top(); ch.pop();
    if(op == '+') shu.push((y + x + mod) % mod);
    if(op == '-') shu.push((y - x + mod) % mod);
    if(op == '*') shu.push(y * x % mod);
    if(op == '^') shu.push(ksm(y, x, mod));
}
/*
void read(){
    len = 0;
    memset(a, 0, sizeof(a));
    char cha=getchar();
    while(1)
    {
        if(cha=='\n' || cha == '\r')//过滤掉回车
        {
            return;
        }
        if(cha==' ')  cha=getchar();//过滤掉空格
        if(cha!=' ')
        {
            a[len++]=cha;
            cha=getchar();
        }
    }
}
*/
void get(char a[])
{
    char c=getchar();
    len = 0;
    while(c=='\n'||c=='\r') c=getchar();
    while(c!='\n'&&c!='\r')
    {
        if(c != ' ')
            a[len ++]=c;
        c=getchar();
    }
}
void jisuan(int check, int c){
    int flag = 0; ll temp = 0;
    for(int i = 0 ; i < len ; ++ i){
        if(is_num(a[i])){
            temp = temp * 10 + a[i] - '0';
            flag = 1;
        }
        else{
            if(flag){
                shu.push(temp);
                flag = 0; temp = 0;
            }
            if(a[i] == 'a'){
                temp = check; flag = 1;
                continue;
            }
            if(a[i] == '('){
                ch.push(a[i]); continue;
            }
            else if(a[i] == ')'){
                while(ch.top() != '('){
                    cal();
                }
                ch.pop();
                continue;
            }
            if(ch.empty()) ch.push(a[i]);
            else{
                while(!ch.empty() && f(ch.top()) >= f(a[i])){
                    cal();
                }
                ch.push(a[i]);
            }
        }
    }
    if(flag){
        shu.push(temp);
        flag = 0; temp = 0;
    }
    while(!ch.empty()) cal();
    v[c] = shu.top();
    //cout<<shu.top()<<endl;
    while(!ch.empty()) ch.pop();
    while(!shu.empty()) shu.pop();
}
int main()
{
    memset(vis, -1, sizeof(vis));
    get(a);
    //cout << "!" << endl;
    for(int q = 0 ; q < 5 ; ++ q){
        jisuan(w[q], q);
        u[q] = v[q];
    }
    //cout << "!!" << endl;
    scanf("%d", &t);
    for(int p = 0 ; p < t ; ++ p){
        get(a);
       // cout << "!" << endl;
        //puts(a);
        if(!is_kuo()) continue;
        int judge = 1;
        for(int q = 0 ; q < 5 ; ++ q){
            //cout << 1 << endl;
            jisuan(w[q], q);
        //cout << 2 << endl;
            if(u[q] != v[q]) judge = 0;
            //cout<<v[q]<<endl;
        }
        if(judge)
            vis[++cnt] = p;
    }
    for(int i = 1 ; i <= cnt ; ++ i)
        if(vis[i] >= 0)
            printf("%c", vis[i] + 'A');
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值